2010-12-21 17 views
29

在Android上解壓縮文件似乎非常慢。起初我以爲這只是模擬器,但它在手機上似乎是一樣的。我已經嘗試了不同的壓縮級別,並最終下降到存儲模式,但仍需要很長時間。如何加快Java/Android中的解壓縮時間?

無論如何,一定有一個理由!有沒有其他人有這個問題?我的解壓方法是這樣的:

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); 

} 
    } 
+1

考慮解壓縮的位置。語境。getCacheDir()將成爲內部存儲,其中Environment.getDataDirectory()可能在內部(或不在),而Environment.getExternalDirectory()將在SD卡上。內部記憶幾乎肯定會變得更快。 – 2010-12-21 23:06:06

回答

63

我不知道,如果解壓Android上是緩慢的,但在一個循環字節複製字節肯定減緩下來,甚至更多。嘗試使用BufferedInputStream和BufferedOutputStream - 它可能會更復雜一些,但根據我的經驗,最終它是值得的。

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

然後你就可以用類似的東西寫:

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

爲什麼不把BufferedInputStream放在FileInputStream和ZipInputStream之間? I.e.`FileInputStream fin = new FileInputStream(zipFile); BufferedInputStream bin = new BufferedInputStream(fin); ZipInputStream zin = new ZipInputStream(bin);` – 2010-12-21 23:43:06

+0

真棒 - 我會給它一個機會 – digitalWestie 2010-12-22 11:21:55

+1

如果讀取和寫入操作像樣本循環那樣在數組上執行,那麼包裝流緩衝流的好處就會減少。當消費者/生產者不能使用字節數組時,緩衝流提供了性能改進,並逐字節地執行操作。 – 2012-04-23 19:45:50

18

感謝您的解決方案羅伯特。 我修改了我的unizip方法,現在只需要幾秒而不是2分鐘。 也許有人對我的解決方案感興趣。所以,在這裏你去:

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(); 
     } 
} 
4

,幫助我瞭解如何壓縮和解壓縮,可以發現here的URL。

我用這個URL與上面的user3203118的答案聯合解壓縮。這是面向這個問題並需要幫助解決問題的人的未來參考。

下面是ZipManager代碼我使用:

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(); 
     } 
    } 
} 
3

只是調用這個方法,它會給你更好的性能..

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(); 
    } 
} 
0

在使用的BufferedOutputStream的情況下,一定要衝洗它。如果你不這樣做,大小比緩衝區小就不能正確地

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(); 
      } 
7

更新2016

使用從其他來源上面的思路和想法,我創造了這個類

創建這個新的解壓

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(); 
    } 
    } 
} 

用法

只是通過你的文件升zip文件的ocation和你的目的地位置這一類
例如

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(); 

不要忘記在清單中添加以下權限(也運行一次許可,如果版本比MARSHMELLOW更高)

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

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

希望這有助於

相關問題