Gibt es eine existierende Methode oder muss ich den exe Block manuell analysieren und überspringen, bevor ich die Daten an ZipInputStream übergebe?
Nach der Überprüfung des EXE-Dateiformats und der ZIP-Dateiformat und das Testen verschiedener Optionen scheint die einfachste Lösung zu sein, einfach jede Präambel bis zum ersten ZIP-Dateikopf zu ignorieren.
Ich habe einen Eingabestream-Filter geschrieben, um die Präambel zu umgehen, und es funktioniert perfekt:
%Vor%WinZipInputStream.java
%Vor%Das Schöne an ZIP-Dateien ist ihre sequentielle Struktur: Jeder Eintrag besteht aus einer unabhängigen Menge von Bytes und am Ende befindet sich ein Zentraler Verzeichnisindex , der alle Einträge und ihre Versätze in der Datei auflistet.
Das Schlimmste ist, dass die java.util.zip.*
-Klassen diesen Index ignorieren und einfach anfangen, in die Datei zu lesen, und erwarten, dass der erste Eintrag ein Lokaler Dateikopf -Block ist, was nicht der Fall ist selbstextrahierende ZIP-Archive (diese beginnen mit dem EXE-Teil).
Vor einigen Jahren habe ich einen eigenen ZIP-Parser geschrieben, um einzelne ZIP-Einträge (LFH + -Daten) zu extrahieren, die sich auf die CDI verlassen, um herauszufinden, wo sich diese Einträge in der Datei befinden. Ich habe es nur überprüft und es kann die Einträge eines selbst-exportierenden ZIP-Archivs ohne weiteres auflisten und Ihnen die Offsets geben - so könnten Sie entweder:
Verwenden Sie diesen Code, um den ersten LFH nach dem EXE-Teil zu finden, und kopieren Sie alles nach in einen anderen : File
und füttern Sie dann das neue File
mit java.util.zip.ZipFile
Bearbeiten: Das Überspringen des EXE-Teils scheint nicht zu funktionieren, ZipFile
liest es immer noch nicht und mein natives ZIP-Programm beschwert sich, dass die neue ZIP-Datei beschädigt ist und genau die Nummer von Bytes, die ich überspringe, werden als "fehlend" angegeben (so dass es tatsächlich die CDI liest). Ich denke, einige Header müssten neu geschrieben werden, so dass der zweite Ansatz vielversprechend erscheint - oder
java.util.zip
); dies würde einige zusätzliche Installationen erfordern, da der Code ursprünglich nicht als Ersatz-ZIP-Bibliothek gedacht war, sondern einen sehr spezifischen Anwendungsfall (differenzielle Aktualisierung von ZIP-Dateien über HTTP) aufwies Der Code wird auf der SourceForge-Projektseite gehostet, Website ) und unter Apache License 2.0 lizenziert, so dass die kommerzielle Nutzung in Ordnung ist - AFAIK gibt es ein kommerzielles Spiel, das es als Updater für ihre Spielinhalte verwendet.
Die interessanten Teile, um die Offsets einer ZIP-Datei zu erhalten, sind Indexer.parseZipFile
, die ein LinkedHashMap<Resource, Long>
zurückgibt (so hat der erste Karteneintrag den niedrigsten Offset in der Datei). Hier ist der Code, den ich verwendet habe, um die Einträge eines selbstextrahierenden ZIP-Archivs aufzulisten (erstellt mit dem WinZIP SE-Ersteller mit Wine auf Ubuntu von einem Acra Release-Datei):
Sie können wahrscheinlich den größten Teil des Codes mit Ausnahme der Pakete Indexer
und zip
, die alle Header-Parsing-Klassen enthalten, herausreißen.
In einigen selbstextrahierenden ZIP-Dateien gibt es gefälschte Local File Header -Marker. Ich denke, es ist am besten, eine Datei rückwärts zu scannen, um den Eintrag End Of Central Directory zu finden. EOCD Datensatz enthält den Offset eines zentralen Verzeichnisses und CD enthält den Offset des ersten lokalen Dateiheaders . Wenn Sie vom ersten Byte eines lokalen Dateiheaders lesen, funktioniert ZipInputStream
einwandfrei.
Offensichtlich ist der folgende Code nicht die schnellste Lösung. Wenn Sie große Dateien verarbeiten, sollten Sie eine Art Pufferung implementieren oder Speicherabbilddateien verwenden.
%Vor%TrueZip funktioniert in diesem Fall am besten. (Atleast in meinem Fall)
Die selbstextrahierende Zip-Datei hat das folgende Format code1 header1 file1 (während eine normale Zip-Datei das Format header1 file1 hat) ... Der Code sagt aus, wie die ZIP extrahiert werden soll
Obwohl das Truetzip-Extraktionsprogramm über die zusätzlichen Bytes klagt und eine Ausnahme auslöst
Hier ist der Code
%Vor%Sie können diese Methode wie Extract (new String ("C: \ 2006Production.exe"), neuer String ("c: \"), "");
aufrufenDie Datei wird im Laufwerk c ... extrahiert. Sie können Ihre Datei selbst bearbeiten. Ich hoffe, das hilft.
Danke.