Android:解压缩文件会引发数据错误或CRC错误

时间:2012-06-15 21:49:20

标签: android exception zip

我正在开发一个下载zip文件并在本地解压缩的项目。我遇到的问题是解压缩过程在5%的时间内起作用。

在这一点上,这对我来说是一个谜,因为有时它会起作用,但大多数时候它会抛出数据或crc错误。即使zip文件没有改变,它甚至会在错误之间切换。

我尝试过多种工具创建的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)

任何人都知道为什么我会收到这些错误?我没有随处可见。

1 个答案:

答案 0 :(得分: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)。否则,您正在编写或阅读的内容最终可能会包含垃圾数据。前者(读取(缓冲区))将始终读取整个缓冲区,但实际上可能没有完整的缓冲区,例如,如果循环的最后一次迭代只读取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();