Autor Beitrag
Kenpachi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 30

Win Vista, Win 7
C#, VB, ASP.NET (VS 2010 Express)
BeitragVerfasst: Sa 06.02.10 05:10 
Hallo, wertes Forum.

Ich habe ein Problem mit einer Methode, die die zlib-komprimierten Bytes der Table, bzw. einer Datei in einem Archiv dekomprimiert und als Array zurück gibt.
Hier besagte Methode:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
public static byte[] DecompressBytes(byte[] CompressedBytes, int BufferLenght)
{
    byte[] Buffer = new byte[BufferLenght];
    byte[] DecompressedData;
    using (MemoryStream ms = new MemoryStream())
    {
        using (MemoryStream ms2 = new MemoryStream(CompressedBytes))
        {
            ms2.ReadByte();
            ms2.ReadByte();
            using (DeflateStream ds = new DeflateStream(ms2, CompressionMode.Decompress))
            {
                int Count;
                while ((Count = ds.Read(Buffer, 0, BufferLenght)) > 0)
                {
                    ms.Write(Buffer, 0, Count);
                }
            }
        }
        DecompressedData = ms.ToArray();
    }
    return DecompressedData;
}


So, nun fang ich an, meine Datei einzulesen und zu bestimmen, ob sie auch wirklich das richtige Dateiformat aufweist und dieses die richtige Version hat und lesen die Table aus:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
Archive.MoM = br.ReadBytes(15);
Archive.WaterMark = br.ReadBytes(15);
Archive.TableOffset = br.ReadUInt32();
Archive.Seeds = br.ReadUInt32();
Archive.FileCount = br.ReadUInt32();
Archive.Version = br.ReadUInt32();
// ... Überprüfen des Dateiformates...
br.BaseStream.Position += Archive.TableOffset;
Archive.TrueFileCount = Archive.FileCount - Archive.Seeds - 7;
Archive.TableSizeCompressed = br.ReadUInt32();
Archive.TableSizeDecompressed = br.ReadUInt32();
Archive.TableCompressed = new byte[Archive.TableSizeCompressed];
br.Read(Archive.TableCompressed, 0, (int)Archive.TableSizeCompressed);
Archive.TableDecompressed = DecompressBytes(Archive.TableCompressed, 1024);


In der letzten Zeile wird die Methode das erste Mal aufgerufen, um zu überprüfen ob die Table-Größe korrekt ist. An dieser Stelle ist Archive.TableCompressed ein 798445 Felder großes Byte-Array und DecompressBytes funktioniert prächtig.
Wenn ich nun aber anfange, die erste Datei auszulesen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
int Offset = 0;
for (int i = 0; i < Archive.TrueFileCount; i++)
{
    string FileName = "";
    while ((char)Archive.TableDecompressed[Offset] != '\0')
        FileName += (char)Archive.TableDecompressed[Offset++];
    Offset++;
    GrfContent CurrentFile = new GrfContent();
    CurrentFile.NameString = FileName;
    CurrentFile.NameByte = Encoding.Default.GetBytes(FileName);
    CurrentFile.LenghtCompressed = BitConverter.ToUInt32(Archive.TableDecompressed, Offset);
    Offset += 4;
    CurrentFile.LenghtAligned = BitConverter.ToUInt32(Archive.TableDecompressed, Offset);
    Offset += 4;
    CurrentFile.LenghtDecompressed = BitConverter.ToUInt32(Archive.TableDecompressed, Offset);
    Offset += 4;
    CurrentFile.Flags = Archive.TableDecompressed[Offset++];
    CurrentFile.Position = BitConverter.ToUInt32(Archive.TableDecompressed, Offset);
    br.BaseStream.Position = CurrentFile.Position + 46;
    CurrentFile.FileContentCompressed = new byte[CurrentFile.LenghtCompressed];
    br.Read(CurrentFile.FileContentCompressed, 0, (int)CurrentFile.LenghtCompressed);
    CurrentFile.FileContentDecompressed = DecompressBytes(CurrentFile.FileContentCompressed, 1024);
    // ... Restliche Aktionen
}

Soweit sollte eigentlich alles geklappt haben, da CurrentFile.NameString einen vernünftigen Wert beinhaltet und es wird mit CurrentFile.FileContentCompressed ein 8729 Felder großes Byte-Array übergeben. Allerdings produziert DecompressBytes nun einen Fehler.
An der Stelle while ((Count = ds.Read(Buffer, 0, BufferLenght)) > 0) wird gemeldet, dass die Blocklänge nicht dem Komplement entspricht. (InvalidDataException)
Tja, damit kann ich leider nicht wirklich etwas anfangen und konnte auch mit Google keine hilfreichen Hinweise finden.
Falls es wichtig ist... Es wird versucht, die Bytes einer Bitmap-Datei zu dekomprimieren.

Hier noch eine bescheidene Information zum Dateiformat: lunardew.com/topic/11
Eine bessere Erklärung konnte ich leider nirgendwo finden.



// EDIT:
Wenn ich es mit der zlib.dll und einer angepassten Mehtode probiere, funktioniert es leider auch nicht.
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
        public byte[] DecompressBytes(byte[] bytes)
        {
            byte[] nbytes = new byte[1024];
            byte[] decompressedData = new byte[0];
            using (MemoryStream ms2 = new MemoryStream())
            {
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    using (ZOutputStream ds = new ZOutputStream(ms2))
                    {
                        int offset = 0;
                        while ((offset = ms.Read(nbytes, 0, nbytes.Length)) > 0)
                        {
                            ds.Write(nbytes, 0, offset);
                        }
                        decompressedData = ms2.ToArray();
                    }
                }
            }
            return decompressedData;
        }

Ich bekomme nun - wieder sobald die erste Datei (.bmp) bearbeitet werden soll - eine ZStreamException (inflating: unknown compression method) an der Stelle ds.Write(nbytes, 0, offset);... Es steht aber unumstößlich fest, dass die diese Datei zlib-komprimiert ist, daher bin ich echt ratlos.


Ich bin wie immer über jede Hilfe froh. :)

//EDIT 11.02.2010
Hat sich erledigt, hab das Dekomprimieren der einzelnen Dateien ausgelagert und nun geht, warum auch immer...
svn.cs-hro.de/eaIEC/eaIEC/Classes/GRF.cs


MfG