Wie entpacke ich Dateien programmgesteuert in Android?
131
Ich benötige ein kleines Code-Snippet, das einige Dateien aus einer bestimmten ZIP-Datei entpackt und die separaten Dateien entsprechend dem Format der komprimierten Datei angibt. Bitte poste dein Wissen und hilf mir.
<Verwendet-Erlaubnis android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />
Lou Morda
1
Ich denke ja, es funktioniert, weil es sehr üblich ist, Dinge auszupacken. Schaffe es einfach, den richtigen "Pfad" und "Postleitzahl" zu finden. Ich habe auch einige Dinge gesehen, die Sie interessieren könnten (sicher, dass Sie sie bereits gesehen haben): link
Vasily Sochinsky
1
Weil Sie die "Nur-Datei" -Operationen überspringen müssen, wenn Sie zeein Verzeichnis sind. Der Versuch, diese Vorgänge auszuführen, führt zu einer Ausnahme.
Vasily Sochinsky
1
Diese Antwort sollte nicht funktionieren, da sie nicht die fehlenden Dateien erstellt, um Daten darauf zu schreiben !!
Omar HossamEldin
1
Tatsächlich funktioniert dieser Code nicht, wenn die Zip-Datei ohne Junk-Pfad erstellt wird. Sie können diesen Code beispielsweise ausführen, um eine APK-Datei zu entpacken. Sie erhalten FileNotFoundException.
Shaw
99
Basierend auf Vasily Sochinskys Antwort etwas optimiert & mit einer kleinen Korrektur:
publicstaticvoid unzip(File zipFile,File targetDirectory)throwsIOException{ZipInputStream zis =newZipInputStream(newBufferedInputStream(newFileInputStream(zipFile)));try{ZipEntry ze;int count;byte[] buffer =newbyte[8192];while((ze = zis.getNextEntry())!=null){File file =newFile(targetDirectory, ze.getName());File dir = ze.isDirectory()? file : file.getParentFile();if(!dir.isDirectory()&&!dir.mkdirs())thrownewFileNotFoundException("Failed to ensure directory: "+
dir.getAbsolutePath());if(ze.isDirectory())continue;FileOutputStream fout =newFileOutputStream(file);try{while((count = zis.read(buffer))!=-1)
fout.write(buffer,0, count);}finally{
fout.close();}/* if time should be restored as well
long time = ze.getTime();
if (time > 0)
file.setLastModified(time);
*/}}finally{
zis.close();}}
Bemerkenswerte Unterschiede
public static - Dies ist eine statische Dienstprogrammmethode, die überall verwendet werden kann.
2 FileParameter, weil String: / für Dateien und man konnte nicht angeben, wo die Zip-Datei vorher extrahiert werden soll. Auch path + filenameVerkettung> https://stackoverflow.com/a/412495/995891
throws- weil spät fangen - fügen Sie einen Versuch fangen, wenn Sie wirklich nicht an ihnen interessiert sind.
stellt tatsächlich sicher, dass die erforderlichen Verzeichnisse in allen Fällen vorhanden sind. Nicht jede Zip-Datei enthält alle erforderlichen Verzeichniseinträge vor den Dateieinträgen. Dies hatte 2 mögliche Fehler:
Wenn die Zip-Datei ein leeres Verzeichnis enthält und anstelle des resultierenden Verzeichnisses eine vorhandene Datei vorhanden ist, wurde dies ignoriert. Der Rückgabewert vonmkdirs() ist wichtig.
könnte bei Zip-Dateien abstürzen, die keine Verzeichnisse enthalten.
Wenn die Größe des Schreibpuffers erhöht wird, sollte dies die Leistung etwas verbessern. Die Speicherung erfolgt normalerweise in 4k-Blöcken, und das Schreiben in kleineren Blöcken ist normalerweise langsamer als erforderlich.
nutzt die Magie von finally, um Ressourcenlecks zu verhindern.
Hallo, ich bekomme einen Pfad mit einem Schrägstrich wie sdcard / temp / 768 \ 769.json, damit ich einen Fehler bekomme. Kannst du mir sagen, wie ich damit
umgehen soll?
@AndoMasahashi das sollte ein legaler Dateiname auf einem Linux-Dateisystem sein. Welchen Fehler bekommen Sie und wie sollte der Dateiname am Ende aussehen?
Zapl
es sieht aus wie /sdcard/pictures\picturess.jpeg und Fehlerdatei nicht gefunden Fehler
Ando Masahashi
Es funktioniert einwandfrei, löst jedoch eine Ausnahme aus, wenn einer der Dateinamen in zip nicht vorhanden ist UTF8 format. Also habe ich stattdessen diesen Code verwendet, der die Bibliothek von Apache verwendet commons-compress.
Während die Antworten, die bereits hier sind, gut funktionieren, stellte ich fest, dass sie etwas langsamer waren, als ich gehofft hatte. Stattdessen habe ich zip4j verwendet , was meiner Meinung nach aufgrund seiner Geschwindigkeit die beste Lösung ist. Es erlaubte auch verschiedene Optionen für das Ausmaß der Komprimierung, was ich nützlich fand.
Denken Sie, dass der gleiche Code zum Entpacken oder Entpacken der APB-Erweiterungsdateien von obb funktioniert?
LOG_TAG
2
Minimales Beispiel Ich habe eine bestimmte Datei aus meiner Zip-Datei in meinen Anwendungs-Cache-Ordner entpackt. Ich habe dann die Manifestdatei mit einer anderen Methode gelesen.
Ich arbeite mit Zip-Dateien, die die ZipFile-Klasse von Java nicht verarbeiten kann. Java 8 kann anscheinend nicht mit der Komprimierungsmethode 12 umgehen (bzip2, glaube ich). Nachdem ich eine Reihe von Methoden ausprobiert hatte, einschließlich zip4j (was auch bei diesen bestimmten Dateien aufgrund eines anderen Problems fehlschlägt), hatte ich Erfolg mit Apaches Commons-Compress, das zusätzliche Komprimierungsmethoden unterstützt , wie hier erwähnt .
Beachten Sie, dass die unten stehende ZipFile-Klasse nicht die aus java.util.zip ist.
Es ist eigentlich org.apache.commons.compress.archivers.zip.ZipFile, also seien Sie vorsichtig mit den Importen.
Ich sehe immer nur Beiträge mit byte[1024]oderbyte[4096] Puffer, wusste nie, dass es viel größer sein kann, was die Leistung verbessert und immer noch ganz normal funktioniert.
//We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).// The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant// improvement in Copy performance.privateconstint_DefaultCopyBufferSize=81920;
Ich habe es jedoch zurückgerufen, 65536was auch ein Vielfaches von ist, 4096nur um sicher zu gehen.
Die Dokumentation dieser Bibliothek ist gut genug, ich habe nur ein paar Beispiele von dort hinzugefügt. Es ist völlig kostenlos und speziell für Android geschrieben.
Antworten:
Hatte Penos Version etwas optimiert. Die Leistungssteigerung ist spürbar.
quelle
ze
ein Verzeichnis sind. Der Versuch, diese Vorgänge auszuführen, führt zu einer Ausnahme.Basierend auf Vasily Sochinskys Antwort etwas optimiert & mit einer kleinen Korrektur:
Bemerkenswerte Unterschiede
public static
- Dies ist eine statische Dienstprogrammmethode, die überall verwendet werden kann.File
Parameter, weilString
: / für Dateien und man konnte nicht angeben, wo die Zip-Datei vorher extrahiert werden soll. Auchpath + filename
Verkettung> https://stackoverflow.com/a/412495/995891throws
- weil spät fangen - fügen Sie einen Versuch fangen, wenn Sie wirklich nicht an ihnen interessiert sind.mkdirs()
ist wichtig.finally
, um Ressourcenlecks zu verhindern.So
sollte das Äquivalent des Originals tun
quelle
UTF8 format
. Also habe ich stattdessen diesen Code verwendet, der die Bibliothek von Apache verwendetcommons-compress
.Dies ist meine Entpackungsmethode, die ich verwende:
quelle
Android verfügt über eine integrierte Java-API. Schauen Sie sich das Paket java.util.zip an.
Die Klasse ZipInputStream ist das, worauf Sie achten sollten. Lesen Sie ZipEntry aus dem ZipInputStream und speichern Sie es im Dateisystem / Ordner. Aktivieren Sie ein ähnliches Beispiel, um es in eine Zip- Datei zu komprimieren .
quelle
Der Kotlin-Weg
Verwendung
quelle
Während die Antworten, die bereits hier sind, gut funktionieren, stellte ich fest, dass sie etwas langsamer waren, als ich gehofft hatte. Stattdessen habe ich zip4j verwendet , was meiner Meinung nach aufgrund seiner Geschwindigkeit die beste Lösung ist. Es erlaubte auch verschiedene Optionen für das Ausmaß der Komprimierung, was ich nützlich fand.
quelle
UPDATE 2016 verwendet die folgende Klasse
Wie benutzt man
Berechtigungen
quelle
Laut @zapl Antwort, Entpacken mit Fortschrittsbericht:
quelle
-> Helferklasse (Unzipper.java)
-> XML-Layout (activity_main.xml):
-> Erlaubnis in der Menifest-Datei:
quelle
Hier ist ein ZipFileIterator (wie ein Java-Iterator, jedoch für Zip-Dateien):
quelle
Minimales Beispiel Ich habe eine bestimmte Datei aus meiner Zip-Datei in meinen Anwendungs-Cache-Ordner entpackt. Ich habe dann die Manifestdatei mit einer anderen Methode gelesen.
quelle
Ich arbeite mit Zip-Dateien, die die ZipFile-Klasse von Java nicht verarbeiten kann. Java 8 kann anscheinend nicht mit der Komprimierungsmethode 12 umgehen (bzip2, glaube ich). Nachdem ich eine Reihe von Methoden ausprobiert hatte, einschließlich zip4j (was auch bei diesen bestimmten Dateien aufgrund eines anderen Problems fehlschlägt), hatte ich Erfolg mit Apaches Commons-Compress, das zusätzliche Komprimierungsmethoden unterstützt , wie hier erwähnt .
Beachten Sie, dass die unten stehende ZipFile-Klasse nicht die aus java.util.zip ist.
Es ist eigentlich org.apache.commons.compress.archivers.zip.ZipFile, also seien Sie vorsichtig mit den Importen.
Für Gradle:
quelle
Basierend auf der Antwort von zapl werden durch Hinzufügen von
try()
AroundCloseable
die Streams nach der Verwendung automatisch geschlossen.Verwenden von
Constant.DefaultBufferSize
(65536
) vonC# .NET 4
Stream.CopyTo aus Jon Skeets Antwort hier: https://stackoverflow.com/a/411605/1876355Ich sehe immer nur Beiträge mit
byte[1024]
oderbyte[4096]
Puffer, wusste nie, dass es viel größer sein kann, was die Leistung verbessert und immer noch ganz normal funktioniert.Hier ist der
Stream
Quellcode: https://referencesource.microsoft.com/#mscorlib/system/io/stream.csIch habe es jedoch zurückgerufen,
65536
was auch ein Vielfaches von ist,4096
nur um sicher zu gehen.quelle
Passwortgeschützte Zip-Datei
Wenn Sie Dateien mit einem Kennwort komprimieren möchten, können Sie sich diese Bibliothek ansehen Dateien mit einem Kennwort einfach können:
Postleitzahl:
Entpacken:
Rar:
Die Dokumentation dieser Bibliothek ist gut genug, ich habe nur ein paar Beispiele von dort hinzugefügt. Es ist völlig kostenlos und speziell für Android geschrieben.
quelle