Comment décompresser les fichiers par programmation sous Android?

J’ai besoin d’un petit extrait de code qui décompresse quelques fichiers d’un fichier .zip donné et donne les fichiers séparés en fonction du format dans lequel ils se trouvaient dans le fichier compressé. Merci de poster vos connaissances et de m’aider.

Si la version de peno était un peu optimisée. L’augmentation des performances est perceptible.

private boolean unpackZip(Ssortingng path, Ssortingng zipname) { InputStream is; ZipInputStream zis; try { Ssortingng filename; is = new FileInputStream(path + zipname); zis = new ZipInputStream(new BufferedInputStream(is)); ZipEntry ze; byte[] buffer = new byte[1024]; int count; while ((ze = zis.getNextEntry()) != null) { // zapis do souboru filename = ze.getName(); // Need to create directories if not exists, or // it will generate an Exception... if (ze.isDirectory()) { File fmd = new File(path + filename); fmd.mkdirs(); continue; } FileOutputStream fout = new FileOutputStream(path + filename); // cteni zipu a zapis while ((count = zis.read(buffer)) != -1) { fout.write(buffer, 0, count); } fout.close(); zis.closeEntry(); } zis.close(); } catch(IOException e) { e.printStackTrace(); return false; } return true; } 

Basé sur la réponse de Vasily Sochinsky un peu tordue et avec une petite correction:

 public static void unzip(File zipFile, File targetDirectory) throws IOException { ZipInputStream zis = new ZipInputStream( new BufferedInputStream(new FileInputStream(zipFile))); try { ZipEntry ze; int count; byte[] buffer = new byte[8192]; while ((ze = zis.getNextEntry()) != null) { File file = new File(targetDirectory, ze.getName()); File dir = ze.isDirectory() ? file : file.getParentFile(); if (!dir.isDirectory() && !dir.mkdirs()) throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath()); if (ze.isDirectory()) continue; FileOutputStream fout = new FileOutputStream(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(); } } 

Différences notables

  • public static – il s’agit d’une méthode d’utilitaire statique qui peut être n’importe où.
  • 2 File parameters de File car Ssortingng sont: / pour les fichiers et on ne peut pas spécifier où le fichier zip doit être extrait auparavant. Aussi path + filename concaténation de path + filename > https://stackoverflow.com/a/412495/995891
  • throws – parce que les captures tardives – ajoutent une prise d’essai si cela ne les intéresse pas vraiment.
  • fait en sorte que les répertoires requirejs existent dans tous les cas. Tous les zip ne contiennent pas toutes les entrées de répertoire requirejses avant les entrées de fichier. Cela a eu 2 bugs potentiels:
    • si le fichier zip contient un répertoire vide et à la place du répertoire résultant, il existe un fichier existant, cela a été ignoré. La valeur de retour de mkdirs() est importante.
    • pourrait tomber en panne sur les fichiers zip qui ne contiennent pas de répertoires.
  • augmentation de la taille du tampon d’écriture, cela devrait améliorer un peu les performances. Le stockage est généralement en blocs de 4 Ko et l’écriture en blocs plus petits est généralement plus lente que nécessaire.
  • utilise la magie de finally pour empêcher les fuites de ressources.

Alors

 unzip(new File("/sdcard/pictures.zip"), new File("/sdcard")); 

devrait faire l’équivalent de l’original

 unpackZip("/sdcard/", "pictures.zip") 

C’est ma méthode de décompression que j’utilise:

 private boolean unpackZip(Ssortingng path, Ssortingng zipname) { InputStream is; ZipInputStream zis; try { is = new FileInputStream(path + zipname); zis = new ZipInputStream(new BufferedInputStream(is)); ZipEntry ze; while((ze = zis.getNextEntry()) != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int count; Ssortingng filename = ze.getName(); FileOutputStream fout = new FileOutputStream(path + filename); // reading and writing while((count = zis.read(buffer)) != -1) { baos.write(buffer, 0, count); byte[] bytes = baos.toByteArray(); fout.write(bytes); baos.reset(); } fout.close(); zis.closeEntry(); } zis.close(); } catch(IOException e) { e.printStackTrace(); return false; } return true; } 

Android possède une API Java intégrée. Découvrez le package java.util.zip .

La classe ZipInputStream est ce que vous devriez examiner. Lisez ZipEntry dans ZipInputStream et videz-le dans le système de fichiers / le dossier. Vérifiez un exemple similaire pour compresser dans un fichier zip .

Alors que les réponses qui sont déjà là fonctionnent bien, j’ai trouvé qu’elles étaient légèrement plus lentes que je l’avais espéré. Au lieu de cela, j’ai utilisé zip4j , qui, à mon avis, est la meilleure solution en raison de sa rapidité. Il a également permis différentes options pour la quantité de compression, ce que j’ai trouvé utile.

Selon @zapl répondez, décompressez avec le rapport de progression:

 public interface UnzipFile_Progress { void Progress(int percent, Ssortingng FileName); } // unzip(new File("/sdcard/pictures.zip"), new File("/sdcard")); public static void UnzipFile(File zipFile, File targetDirectory, UnzipFile_Progress progress) throws IOException, FileNotFoundException { long total_len = zipFile.length(); long total_installed_len = 0; ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(zipFile))); try { ZipEntry ze; int count; byte[] buffer = new byte[1024]; while ((ze = zis.getNextEntry()) != null) { if (progress != null) { total_installed_len += ze.getCompressedSize(); Ssortingng file_name = ze.getName(); int percent = (int)(total_installed_len * 100 / total_len); progress.Progress(percent, file_name); } File file = new File(targetDirectory, ze.getName()); File dir = ze.isDirectory() ? file : file.getParentFile(); if (!dir.isDirectory() && !dir.mkdirs()) throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath()); if (ze.isDirectory()) continue; FileOutputStream fout = new FileOutputStream(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(); } } 

MISE À JOUR 2016 utilise la classe suivante

  package com.example.zip; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import android.util.Log; public class DecompressFast { private Ssortingng _zipFile; private Ssortingng _location; public DecompressFast(Ssortingng zipFile, Ssortingng location) { _zipFile = zipFile; _location = location; _dirChecker(""); } public void unzip() { try { FileInputStream fin = new FileInputStream(_zipFile); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; while ((ze = zin.getNextEntry()) != null) { Log.v("Decompress", "Unzipping " + ze.getName()); if(ze.isDirectory()) { _dirChecker(ze.getName()); } else { FileOutputStream fout = new FileOutputStream(_location + ze.getName()); BufferedOutputStream bufout = new BufferedOutputStream(fout); byte[] buffer = new byte[1024]; int read = 0; while ((read = zin.read(buffer)) != -1) { bufout.write(buffer, 0, read); } bufout.close(); zin.closeEntry(); fout.close(); } } zin.close(); Log.d("Unzip", "Unzipping complete. path : " +_location ); } catch(Exception e) { Log.e("Decompress", "unzip", e); Log.d("Unzip", "Unzipping failed"); } } private void _dirChecker(Ssortingng dir) { File f = new File(_location + dir); if(!f.isDirectory()) { f.mkdirs(); } } } 

Comment utiliser

  Ssortingng zipFile = Environment.getExternalStorageDirectory() + "/the_raven.zip"; //your zip file location Ssortingng unzipLocation = Environment.getExternalStorageDirectory() + "/unzippedtestNew/"; // destination folder location DecompressFast df= new DecompressFast(zipFile, unzipLocation); df.unzip(); 

Autorisations

    
 public class MainActivity extends Activity { private Ssortingng LOG_TAG = MainActivity.class.getSimpleName(); private File zipFile; private File destination; private TextView status; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); status = (TextView) findViewById(R.id.main_status); status.setGravity(Gravity.CENTER); if ( initialize() ) { zipFile = new File(destination, "BlueBoxnew.zip"); try { Unzipper.unzip(zipFile, destination); status.setText("Extracted to \n"+destination.getAbsolutePath()); } catch (ZipException e) { Log.e(LOG_TAG, e.getMessage()); } catch (IOException e) { Log.e(LOG_TAG, e.getMessage()); } } else { status.setText("Unable to initialize sd card."); } } public boolean initialize() { boolean result = false; File sdCard = new File(Environment.getExternalStorageDirectory()+"/zip/"); //File sdCard = Environment.getExternalStorageDirectory(); if ( sdCard != null ) { destination = sdCard; if ( !destination.exists() ) { if ( destination.mkdir() ) { result = true; } } else { result = true; } } return result; } } 

-> Helper Class (Unzipper.java)

  import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipInputStream; import android.util.Log; public class Unzipper { private static Ssortingng LOG_TAG = Unzipper.class.getSimpleName(); public static void unzip(final File file, final File destination) throws ZipException, IOException { new Thread() { public void run() { long START_TIME = System.currentTimeMillis(); long FINISH_TIME = 0; long ELAPSED_TIME = 0; try { ZipInputStream zin = new ZipInputStream(new FileInputStream(file)); Ssortingng workingDir = destination.getAbsolutePath()+"/"; byte buffer[] = new byte[4096]; int bytesRead; ZipEntry entry = null; while ((entry = zin.getNextEntry()) != null) { if (entry.isDirectory()) { File dir = new File(workingDir, entry.getName()); if (!dir.exists()) { dir.mkdir(); } Log.i(LOG_TAG, "[DIR] "+entry.getName()); } else { FileOutputStream fos = new FileOutputStream(workingDir + entry.getName()); while ((bytesRead = zin.read(buffer)) != -1) { fos.write(buffer, 0, bytesRead); } fos.close(); Log.i(LOG_TAG, "[FILE] "+entry.getName()); } } zin.close(); FINISH_TIME = System.currentTimeMillis(); ELAPSED_TIME = FINISH_TIME - START_TIME; Log.i(LOG_TAG, "COMPLETED in "+(ELAPSED_TIME/1000)+" seconds."); } catch (Exception e) { Log.e(LOG_TAG, "FAILED"); } }; }.start(); } } 

-> disposition XML (activity_main.xml):

    

-> autorisation dans le fichier Menifest:

  

La voie Kotlin

 //FileExt.kt data class ZipIO (val entry: ZipEntry, val output: File) fun File.unzip(unzipLocationRoot: File? = null) { val rootFolder = unzipLocationRoot ?: File(parentFile.absolutePath + File.separator + nameWithoutExtension) if (!rootFolder.exists()) { rootFolder.mkdirs() } ZipFile(this).use { zip -> zip .ensortinges() .asSequence() .map { val outputFile = File(rootFolder.absolutePath + File.separator + it.name) ZipIO(it, outputFile) } .map { it.output.parentFile?.run{ if (!exists()) mkdirs() } it } .filter { !it.entry.isDirectory } .forEach { (entry, output) -> zip.getInputStream(entry).use { input -> output.outputStream().use { output -> input.copyTo(output) } } } } } 

Usage

 val zipFile = File("path_to_your_zip_file") file.unzip() 

Voici un ZipFileIterator (comme un iterator java, mais pour les fichiers zip):

 package ch.epfl.bbp.io; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Iterator; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class ZipFileIterator implements Iterator { private byte[] buffer = new byte[1024]; private FileInputStream is; private ZipInputStream zis; private ZipEntry ze; public ZipFileIterator(File file) throws FileNotFoundException { is = new FileInputStream(file); zis = new ZipInputStream(new BufferedInputStream(is)); } @Override public boolean hasNext() { try { return (ze = zis.getNextEntry()) != null; } catch (IOException e) { e.printStackTrace(); } return false; } @Override public File next() { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int count; Ssortingng filename = ze.getName(); File tmpFile = File.createTempFile(filename, "tmp"); tmpFile.deleteOnExit();// TODO make it configurable FileOutputStream fout = new FileOutputStream(tmpFile); while ((count = zis.read(buffer)) != -1) { baos.write(buffer, 0, count); byte[] bytes = baos.toByteArray(); fout.write(bytes); baos.reset(); } fout.close(); zis.closeEntry(); return tmpFile; } catch (Exception e) { throw new RuntimeException(e); } } @Override public void remove() { throw new RuntimeException("not implemented"); } public void close() { try { zis.close(); is.close(); } catch (IOException e) {// nope } } } 

Exemple minimal J’ai utilisé pour décompresser un fichier spécifique de mon fichier zip dans le dossier cache de mes applications. Je lis alors le fichier manifeste en utilisant une méthode différente.

 private void unzipUpdateToCache() { ZipInputStream zipIs = new ZipInputStream(context.getResources().openRawResource(R.raw.update)); ZipEntry ze = null; try { while ((ze = zipIs.getNextEntry()) != null) { if (ze.getName().equals("update/manifest.json")) { FileOutputStream fout = new FileOutputStream(context.getCacheDir().getAbsolutePath() + "/manifest.json"); byte[] buffer = new byte[1024]; int length = 0; while ((length = zipIs.read(buffer))>0) { fout.write(buffer, 0, length); } zipIs .closeEntry(); fout.close(); } } zipIs .close(); } catch (IOException e) { e.printStackTrace(); } } 

Fichier zip protégé par mot de passe

Si vous voulez compresser des fichiers avec un mot de passe, vous pouvez consulter cette bibliothèque qui peut facilement compresser des fichiers avec un mot de passe:

Zip *: français:

 ZipArchive zipArchive = new ZipArchive(); zipArchive.zip(targetPath,destinationPath,password); 

Décompressez:

 ZipArchive zipArchive = new ZipArchive(); zipArchive.unzip(targetPath,destinationPath,password); 

Rar:

 RarArchive rarArchive = new RarArchive(); rarArchive.extractArchive(file archive, file destination); 

La documentation de cette bibliothèque est suffisante, j’ai juste ajouté quelques exemples à partir de là. C’est totalement gratuit et écrit spécialement pour Android.

Je travaille avec des fichiers zip que la classe ZipFile de Java n’est pas capable de gérer. Java 8 ne peut apparemment pas gérer la méthode de compression 12 (bzip2 je crois). Après avoir essayé un certain nombre de méthodes, dont zip4j (qui échoue également avec ces fichiers particuliers en raison d’un autre problème), j’ai eu du succès avec les commons-compress d’ Apache qui supportent des méthodes de compression supplémentaires comme mentionné ici .

Notez que la classe ZipFile ci-dessous n’est pas celle de java.util.zip.

C’est en fait org.apache.commons.compress.archivers.zip.ZipFile alors soyez prudent avec les importations.

 try (ZipFile zipFile = new ZipFile(archiveFile)) { Enumeration ensortinges = zipFile.getEnsortinges(); while (ensortinges.hasMoreElements()) { ZipArchiveEntry entry = ensortinges.nextElement(); File entryDestination = new File(destination, entry.getName()); if (entry.isDirectory()) { entryDestination.mkdirs(); } else { entryDestination.getParentFile().mkdirs(); try (InputStream in = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(entryDestination)) { IOUtils.copy(in, out); } } } } catch (IOException ex) { log.debug("Error unzipping archive file: " + archiveFile, ex); } 

Pour Gradle:

 comstack 'org.apache.commons:commons-compress:1.18'