首页 文章

使用ZipInputStream解压缩永远不会完成

提问于
浏览
2

我正在使用AsyncTask解压缩一个文件,一切似乎都很顺利(ZIP存档中的所有文件都被解压缩),但我的解压缩方法永远不会完成 .

这是我的解压缩类的来源:

public class MyUnzipper {


    public static boolean unzipFileIntoDirectory(String inputFilename, String outputPath) throws Exception {
        ZipInputStream zis = null;
        BufferedOutputStream dest = null;

        try {
            File archive = new File(inputFilename);
            File destinationDir = new File(outputPath);

            final int BUFFER_SIZE = 1024;

            zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(archive), BUFFER_SIZE));
            ZipEntry entry = null;
            File destFile;
            while( (entry = zis.getNextEntry()) != null ){

                destFile = new File(destinationDir, entry.getName());

                if( entry.isDirectory() ){
                    destFile.mkdirs();
                }
                else {
                    // check for and create parent directories if they don't exist
                    File parentDir = destFile.getParentFile();
                    if ( null != parentDir ) {
                        if ( !parentDir.isDirectory() ) {
                            parentDir.mkdirs();
                        }
                    }

                    int count;
                    byte data[] = new byte[BUFFER_SIZE];
                    dest = new BufferedOutputStream(new FileOutputStream(destFile), BUFFER_SIZE);
                    Log.i("MyUnzipper", "Beginning unzip of " + destFile);

                    while( (count = zis.read(data, 0, BUFFER_SIZE)) != -1 ){ 
                        dest.write(data, 0, count);
                        Log.v("MyUnzipper", "Count = " + count);
                    }
                    dest.flush();
                    dest.close();
                    dest = null;
                }

                zis.closeEntry();

                Log.wtf("MyUnzipper", "Unzipped entry " + entry.getName());
            }

            Log.wtf("MyUnzipper", "Unzip done");
        }
        catch(Exception e){
            Log.wtf("MyUnzipper", "Unzip error");
            e.printStackTrace();
            return false;
        }
        finally {
            if( null != zis )
                zis.close();

            if( null != dest )
                dest.close();
        }

        return true;
    }

}

当我逐行调试时,它运行正常,直到它解压缩所有文件,然后它到达 zis.closeEntry() ,调试器只是"goes away",即下一行( Log.wtf(...) )永远不会被执行 . 我的AsyncTask永远不会完成,它会陷入无限循环?!但是看看 ZipInputStream.closeEntry() 的来源似乎没有任何循环或任何可疑的东西?

我也尝试使用 ZipFile 而不是 ZipInputStream 解压缩ZIP存档,但后来我收到以下错误:

java.util.zip.ZipException: End Of Central Directory signature not found

ZIP文件没有任何问题,我在Mac OSx上使用 zip -v -T 进行了测试 . 我也尝试使用ZIP版本3.0和2.1重新压缩它(原始版本为2.0) . 我可以在Mac OSx上解压缩所有版本而没有任何问题(使用Unarchiver和Archive Utility) .

这让我疯了,可能出现什么问题?

Update (solved)

原来是一个非常愚蠢的问题,与解压缩无关 .

我在解压缩之前从服务器下载ZIP文件,显然我忘记在开始解压缩操作之前在下载操作的输出流上调用 close() .

也许这个主题可以帮助那些犯同样愚蠢错误的人 .

1 回答

  • 4

    好吧,即使您关闭所有以前的输出和输入流,有时您的ZIP提取代码也会卡住 . 并且,这是a known bugZipInputStream#read 可以返回0 .

    Addition:

    如果您的ZIP文件包含一些具有非ACSII文件名的文件,则'll face problem with extracting. Android' s ZipInputStream 与UTF-8,CP437等不兼容 .

    在这种情况下,Apache Commons应该是一个解决方案:

    private boolean unpack(File zipFile, File targetDir) {
        ZipFile zip = null;
        try {
            zip = new ZipFile(zipFile.getAbsoluteFile());
            final Enumeration<ZipArchiveEntry> entries = zip.getEntries();
            while(entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();
                if (entry.isDirectory()) {
                    mkdirsOrThrow(new File(targetDir, entry.getName()));
                    continue;
                }
                final File entryDestination = new File(targetDir,  entry.getName());
                mkdirsOrThrow(entryDestination.getParentFile());
                final InputStream in = zip.getInputStream(entry);
                final OutputStream out = new FileOutputStream(entryDestination);
                IOUtils.copy(in, out);
                IOUtils.closeQuietly(in);
                IOUtils.closeQuietly(out);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (zip!= null) try {
                zip.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }
    

相关问题