3

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

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

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

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

4

1 回答 1

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. 使用输入和输出流时,不要使用 read(buffer) 或 write(buffer) 方法,您需要使用 read/write(buffer,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();
    
于 2012-06-20T18:50:28.993 回答