2012-06-15 95 views
3

我正在開發一個下載zip文件並在本地解壓縮的項目。我遇到的問題是解壓縮過程的工作時間爲5%。Android:解壓縮文件引發數據錯誤或CRC錯誤

在這一點上,對我來說這是一個謎,因爲它有時會起作用,但大多數情況下它會拋出數據或crc錯誤。即使zip文件沒有改變,它甚至會在erros之間切換。

我試過由許多工具創建的zip文件,如果格式不正確。但無濟於事。即使在終端中創建的拉鍊也不起作用。

這裏是我的解壓碼:

try { 
    String _location = model.getLocalPath(); 
    FileInputStream fin = new FileInputStream(localFile); 
    ZipInputStream zin = new ZipInputStream(fin); 
    ZipEntry ze = null; 
    byte[] buffer = new byte[1024]; 
    while((ze = zin.getNextEntry()) != null) { 
     if(_cancel) break; 

     System.out.println("unzipping " + ze.getName()); 

     if(ze.isDirectory()) { 
      File f = new File(_location + ze.getName()); 
      f.mkdirs(); 
     } else { 

      FileOutputStream fout = new FileOutputStream(_location + ze.getName()); 
      for(int c = zin.read(buffer); c > 0; c = zin.read(buffer)) { 
       fout.write(buffer,0,c); 
      } 
      zin.closeEntry(); 
      fout.close(); 
     } 
    } 
    zin.close(); 

    if(_cancel) { 
     handler.post(dispatchCancel); 
     return; 
    } 

} catch(Exception e) { 
    System.out.println("UNZIP ERROR!"); 
    System.out.println(e.getMessage()); 
    System.out.println(e.toString()); 
    e.printStackTrace(); 
} 

這裏是如何我通常會創建的zip文件。

$>zip -r myzip.zip myzip/ 

這裏有兩個錯誤輸出:

java.util.zip.ZipException: CRC mismatch 
    at java.util.zip.ZipInputStream.readAndVerifyDataDescriptor(ZipInputStream.java:209) 
    at java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:173) 
    at com.XX.XX.XXIssueDownloader$7.run(XXIssueDownloader.java:222) 
    at java.lang.Thread.run(Thread.java:1020) 

java.util.zip.ZipException: data error 
    at java.util.zip.ZipInputStream.read(ZipInputStream.java:336) 
    at java.io.FilterInputStream.read(FilterInputStream.java:133) 
    at com.XX.XX.XXIssueDownloader$7.run(XXIssueDownloader.java:219) 
    at java.lang.Thread.run(Thread.java:1020) 

任何人有任何想法,爲什麼我可能會得到這些錯誤?這些都沒有得到。

回答

6

加載Zip文件時有兩件非常重要的事情。

  1. 確保您使用的請求方法不包含Accept-Encoding:標頭。如果它在請求中,那麼響應不是一個zip文件,它是一個gzip壓縮zip文件。因此,如果您在下載時直接將其寫入磁盤,那麼它實際上不會是zip文件。您可以使用類似這樣加載的zip文件:

    URL url = new URL(remoteFilePath); 
    URLConnection connection = url.openConnection(); 
    InputStream in = new BufferedInputStream(connection.getInputStream()); 
    FileOutputStream f = new FileOutputStream(localFile); 
    
    //setup buffers and loop through data 
    byte[] buffer = new byte[1024]; 
    long total = 0; 
    long fileLength = connection.getContentLength(); 
    int len1 = 0; 
    while((len1 = in.read(buffer)) != -1) { 
         if(_cancel) break; 
         total += len1; 
         _Progress = (int) (total * 100/fileLength); 
         f.write(buffer,0,len1); 
         handler.post(updateProgress); 
    } 
    f.close(); 
    in.close(); 
    
  2. 當使用輸入和出流,不使用讀(緩衝)或寫(緩衝)方法,你需要使用讀/寫(緩衝液,0,LEN)。否則,你正在寫或讀的內容可能會以垃圾數據結束。前者(read(buffer))將始終讀取整個緩衝區,但實際上可能沒有完整的緩衝區,例如,如果循環的最後一次迭代只讀取512個字節。因此,這裏是你如何解壓縮文件:

    String _location = model.getLocalPath(); 
    FileInputStream fin = new FileInputStream(localFile); 
    ZipInputStream zin = new ZipInputStream(fin); 
    ZipEntry ze = null; 
    
    while((ze = zin.getNextEntry()) != null) { 
         if(_cancel) break; 
         System.out.println("unzipping " + ze.getName()); 
         System.out.println("to: " + _location + ze.getName()); 
         if(ze.isDirectory()) { 
           File f = new File(_location + ze.getName()); 
           f.mkdirs(); 
         } else { 
           byte[] buffer2 = new byte[1024]; 
           FileOutputStream fout = new FileOutputStream(_location + ze.getName()); 
           for(int c = zin.read(buffer2); c > 0; c = zin.read(buffer2)) { 
             fout.write(buffer2,0,c); 
           } 
           zin.closeEntry(); 
           fout.close(); 
         } 
    } 
    zin.close(); 
    
+1

大,我得到'CRC error',只是因爲下載的zip文件損壞。我在代碼中使用'f.write(buffer,0,len1);'而不是'f.write(buffer)',然後解決了這個問題。謝謝。 – wodong

+0

當我嘗試在我的Android設備上解壓apk文件時,我收到了crcError錯誤。 我猜你們大家正在談論的代碼是用於PC上的Eclipse(或類似的)。如果我想將我的Android設備(Samsung Galaxy Note 2與Android 4.1.2)解壓縮,我該如何避免此錯誤? 謝謝! :) –

+0

@wodong - 我已經在使用f.write(buffer,0,len1);在我回答的代碼示例中 – gngrwzrd