¿Cómo acelerar el tiempo de descompresión en Java / Android?

Descomprimir archivos en android parece ser terriblemente lento. Al principio pensé que esto era sólo el emulador pero parece ser lo mismo en el teléfono. He probado diferentes niveles de compresión y, finalmente, caí en el modo de almacenamiento, pero todavía toma años.

De todos modos, debe haber una razón! ¿Alguien más tiene este problema? Mi método de descompresión se ve así:

public void unzip() { try{ FileInputStream fin = new FileInputStream(zipFile); ZipInputStream zin = new ZipInputStream(fin); File rootfolder = new File(directory); rootfolder.mkdirs(); ZipEntry ze = null; while ((ze = zin.getNextEntry())!=null){ if(ze.isDirectory()){ dirChecker(ze.getName()); } else{ FileOutputStream fout = new FileOutputStream(directory+ze.getName()); for(int c = zin.read();c!=-1;c=zin.read()){ fout.write(c); } //Debug.out("Closing streams"); zin.closeEntry(); fout.close(); } } zin.close(); } catch(Exception e){ //Debug.out("Error trying to unzip file " + zipFile); } } 

No sé si descomprimir en Android es lento, pero copiar byte para byte en un bucle es sin duda la desaceleración aún más. Intente usar BufferedInputStream y BufferedOutputStream – puede ser un poco más complicado, pero en mi experiencia vale la pena al final.

 BufferedInputStream in = new BufferedInputStream(zin); BufferedOutputStream out = new BufferedOutputStream(fout); 

Y entonces usted puede escribir con algo como eso:

 byte b[] = new byte[1024]; int n; while ((n = in.read(b,0,1024)) >= 0) { out.write(b,0,n); } 

Gracias por la solución Robert. He modificado mi método de unizip y ahora sólo toma unos segundos en vez de 2 minutos. Tal vez alguien está interesado en mi solución. Así que aquí tienes:

 public void unzip() { try { FileInputStream inputStream = new FileInputStream(filePath); ZipInputStream zipStream = new ZipInputStream(inputStream); ZipEntry zEntry = null; while ((zEntry = zipStream.getNextEntry()) != null) { Log.d("Unzip", "Unzipping " + zEntry.getName() + " at " + destination); if (zEntry.isDirectory()) { hanldeDirectory(zEntry.getName()); } else { FileOutputStream fout = new FileOutputStream( this.destination + "/" + zEntry.getName()); BufferedOutputStream bufout = new BufferedOutputStream(fout); byte[] buffer = new byte[1024]; int read = 0; while ((read = zipStream.read(buffer)) != -1) { bufout.write(buffer, 0, read); } zipStream.closeEntry(); bufout.close(); fout.close(); } } zipStream.close(); Log.d("Unzip", "Unzipping complete. path : " + destination); } catch (Exception e) { Log.d("Unzip", "Unzipping failed"); e.printStackTrace(); } } public void hanldeDirectory(String dir) { File f = new File(this.destination + dir); if (!f.isDirectory()) { f.mkdirs(); } } 

Actualización 2016

Usando sobre ideas e ideas de algunas otras fuentes que he creado esta clase

Crear esta nueva clase

 package com.example.Unzipdemo; 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 String _zipFile; private String _location; public DecompressFast(String zipFile, String 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(String dir) { File f = new File(_location + dir); if(!f.isDirectory()) { f.mkdirs(); } } } 

USO

Simplemente pase su archivo de ubicación del archivo zip y su ubicación de destino a esta clase
ejemplo

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

No olvides agregar los siguientes permisos en manifesto (también permiso de tiempo de ejecución si la versión es superior a marshmellow)

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 

espero que esto ayude

La URL que me ayudó a aprender Cómo comprimir y descomprimir es la siguiente: https://github.com/javatechig/javatechig-android-advanced/tree/master/com.javatechig.androidzip

Utilicé esa URL en conjunto con la respuesta de user3203118 anterior para descomprimir. Esto es para referencias futuras para las personas que corren en este problema y necesitan ayuda para solucionarlo.

A continuación se muestra el código ZipManager que estoy usando:

 public class ZipManager { private static final int BUFFER = 80000; public void zip(String[] _files, String zipFileName) { try { BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream(zipFileName); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream( dest)); byte data[] = new byte[BUFFER]; for (int i = 0; i < _files.length; i++) { Log.v("Compress", "Adding: " + _files[i]); FileInputStream fi = new FileInputStream(_files[i]); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(_files[i].substring(_files[i] .lastIndexOf("/") + 1)); out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } origin.close(); } out.close(); } catch (Exception e) { e.printStackTrace(); } } public void unzip(String _zipFile, String _targetLocation) { // create target location folder if not exist dirChecker(_targetLocation); try { FileInputStream fin = new FileInputStream(_zipFile); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; while ((ze = zin.getNextEntry()) != null) { // create dir if required while unzipping if (ze.isDirectory()) { dirChecker(ze.getName()); } else { FileOutputStream fout = new FileOutputStream( _targetLocation + "/" + 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); } zin.closeEntry(); bufout.close(); fout.close(); } } zin.close(); } catch (Exception e) { System.out.println(e); } } private void dirChecker(String dir) { File f = new File(dir); if (!f.isDirectory()) { f.mkdirs(); } } } 

Simplemente llame a este método y le dará un rendimiento mucho mejor.

  public boolean unzip(Context context) { try { FileInputStream fin = new FileInputStream(_zipFile); ZipInputStream zin = new ZipInputStream(fin); BufferedInputStream in = new BufferedInputStream(zin); 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 out = new BufferedOutputStream(fout); byte b[] = new byte[1024]; for (int c = in.read(b,0,1024); c != -1; c = in.read()) { out.write(b,0,c); } zin.closeEntry(); fout.close(); } } zin.close(); return true; } catch (Exception e) { Log.e("Decompress", "unzip", e); return false; } } private void _dirChecker(String dir) { File f = new File(_location + dir); if (!f.isDirectory()) { f.mkdirs(); } } 

En caso de utilizar BufferedOutputStream asegúrese de enjuagarlo. Si no lo hace, el tamaño menor que el búfer no se descomprimirá correctamente

 if (ze.isDirectory()) { _dirChecker(ze.getName()); } else { FileOutputStream fout = new FileOutputStream(_location + ze.getName()); BufferedOutputStream out = new BufferedOutputStream(fout); byte buffer[] = new byte[1024]; for (int c = in.read(buffer,0,1024); c != -1; c = in.read()) { out.write(buffer,0,c); } out.flush();//flush it...... zin.closeEntry(); fout.close(); } 
  • ¿Cómo anotación @Inject sabría qué clase concreta instanciar en la misma interfaz?
  • Líneas de desplazamiento de borde azul de listview. Androide
  • Android / Java convertir la fecha de cadena en el tipo largo
  • ListView se desplaza hacia arriba cuando EditText crece
  • Cómo convertir int a typedarray Android
  • NullPointerException en startAnimation (anim)
  • Tema de transmisión en vivo
  • Implementación de la configuración de ahorro
  • Intermitentes marcos lentos en Android OpenGL ES 2.0
  • Control de la intensidad de vibración en los teléfonos Android? ¿Es posible?
  • Problemas con pruebas de instrumentos Espresso en los dispositivos de tiempo de ejecución de Dalvik
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.