7zip Archive und LZMA komprimierte Archivheader. Oder Links zu guten Dekodern :)

d4rkY89

Mitglied
Hi,
ich stehe hier vor einem ziemlich nervtötenden Problem und hoffe es kennt sich jemand mit dem 7z-Archiv und dem LZMA Dekoder aus. Alternativ würden mir auch Links zu gut funktionierenden 7zip Dekodern helfen. JBidings und J7Zip habe ich bereits ausgeschlossen, da JBindings nur ein Wrapper ist, den ich nicht gerne benutze und J7Zip ist ein absolut unstrukturiertes Projekt, dass nicht mehr weiterentwickelt wird und nicht so funktioniet, wie ich es bräuchte.
Also am Liebsten wäre mir etwas, das so funktioniert wie das Entpacken von Zip-Archiven mit der standart Java API.
Da ich bis jetzt nichts gescheites gefunden habe bin ich nun dabei es selber zu machen. Zum dekodieren der Streams im Archiv nutze ich das auf der 7zip Homepage verfügbare SDK. Ich habe ein 7zip Archiv und möchte dieses auslesen. Dabei wurde der Header auch mit dem LZMA Encoder komprimiert in das Archiv geschrieben. Es handelt sich dabei also um einen sogenannten "Packed header". Ich kann bisher das Archiv erfolgreich auslesen und stehe nun nuroch vor dem Problem, dass der LZMA Decoder die Header-Daten nicht dekodieren will :(

Code:
Archive structure
~~~~~~~~~~~~~~~~~  
SignatureHeader
[PackedStreams]
[PackedStreamsForHeaders]
[
  Header 
  or 
  {
    Packed Header
    HeaderInfo
  }
]

Nach dieser Struktur kommt direkt nach dem "Packed Header" (kodierte Header-Daten) die HeaderInfos, die ich bereits korrekt auslese. In den HeaderInfos steht nun unter anderem die Startposition der kodierten Daten für den Header, dessen Größe (bzw. Länge) und welcher Codierer dabei genutzt wurde.

Wenn ich nun die Adresse und die Länge dieser kodierten Headerdaten addiere komm ich genau auf die Startposition der HeaderInfos raus, was auch der Archivstruktur entspricht. Daraus sollte ja logischerweißse folgen, dass die Position und die Länge des Header-Streams korrekt sind.

Wenn ich nun den Decodierer anwende, wie es in einem Beispielcode gemacht wird, dann funktioniert leider nichts mehr. Der Dekodierer bricht direkt nach den ersten paar gelesenen Bytes ab.

Ich habe mir schließlich die ersten 13 Bytes des Streams angeschaut und sie mit der Dokumentation verglichen

Code:
LZMA compressed file format
---------------------------
Offset Size Description
  0     1   Special LZMA properties (lc,lp, pb in encoded form)
  1     4   Dictionary size (little endian)
  5     8   Uncompressed size (little endian). -1 means unknown size
 13         Compressed data

So hier nun mal meine bisherigen Daten, die ich bei meinem Testarchiv bekomme:
Code:
File size: 25738
HeaderInfo pos: 25702
HeaderStream pos: 25513
HeaderStream length: 189
HeaderStream pos + length: 25702  (ergibt genau die "HeaderInfo pos". siehe "Archive structure")
Uncompressed header size: 412 (Aus den HeaderInfos nicht aus dem LZMA Stream)
Die ersten 13 Bytes des kodierten Headers:
[ 0] 00000000
[ 1] 00000000
[ 2] 10000001
[ 3] 00110011
[ 4] 00000111
[ 5] 10101110
[ 6] 00001111
[ 7] 11010111
[ 8] 11101111
[ 9] 11111011
[10] 10101001
[11] 01010010
[12] 01111100

Wenn ich das nun die Bytes 1 bis 12 als betrachte und ins Dezimale umrechne bekomme ich folgende Werte:

Code:
Dictionary size (Bytes 1-4):
Little-Endian: 00000111 00110011 10000001 00000000 = 120815872 Bytes = 115 MBytes Ich denke das ist ein ziemlich unrealistischer Wert um einen Header von wenigen Bytes zu kodieren.
Big-Endian: 00000000 10000001 00110011 00000111 = 8467207 Bytes = 8 MBytes Das ist ein angenehmerer Wert, auch wenn immernoch ziemlich groß und er entspricht nicht dem Little-Endian

Code:
Uncompressed size (Bytes 5-12):
Egal ob nun Little- oder Big-Endian. Beide Werte sind absolut unrealistisch. Der Header wird nicht größer sein als ein paar Bytes. In diesem Fall habe müsste die Größe sogar genau 412 Bytes enstsprechen.

Ich verstehe nun also nicht was diese absolut falschen Werte an einer doch scheinbar richtigen Streamposition zu suchen haben. Irgendwas muss ja nun falsch sein an meinem Code aber ich komm beim besten Willen nicht drauf was es ist. Das einzigste was ich weiß ist, dass die ausgelesenen Positionen wohl stimmen sollten.
Ich habe mir gedacht, dass die letzten 8 Bytes des "LZMA compressed file format" vielleicht entfallen würden, da die Größe des entpackten Headers bereits in den HeaderInfos zu finden sind. Aber das half auch nicht weiter.

Gruß d4rky89
 
Zuletzt bearbeitet:

d4rkY89

Mitglied
Ok, ich habs endlich geschafft. Der Header lässt sich nun dekodieren. Die ersten 13 Bytes, welche die Informationen zur Wörtergröße und Dateigröße beinhalteten waren tatsächlich nicht teil des Headerstreams.
 

DerEisige

Erfahrenes Mitglied
Hallo,

ich bin gerade auch auf der Suche nach einer Möglichkeit, um die gängigen Formate Java intern zu entpacken.

Da du das Problem anscheinen schon gelöst hast, wollte ich mal fragen wie deine Lösung aussieht.

mfg. derEisige