使用 ZipInputStream 解压永远不会完成 [英] Unzipping with ZipInputStream never finishes

查看:84
本文介绍了使用 ZipInputStream 解压永远不会完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 AsyncTask 解压缩文件,一切似乎进展顺利(ZIP 存档中的所有文件都已解压缩),但我的解压缩方法从未完成.

I'm using an AsyncTask to unzip a file, and all seems to be going well (all the files in the ZIP archive are extracted), but my unzip method never finishes.

这是我解压类的源代码:

Here's the source for my unzip class:

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(),调试器就消失"了,即下一行 (Log.wtf(...)) 永远不会执行.我的 AsyncTask 永远不会完成,就好像我陷入了无限循环?!但是查看 ZipInputStream.closeEntry() 的源代码,那里似乎没有任何循环或任何可疑之处?

When I debug this line-by-line, it runs fine until it has unzipped all files, then it gets to zis.closeEntry(), and the debugger just "goes away", i.e. the next line (Log.wtf(...)) is never executed. My AsyncTask is never finished, it's just as if I'm stuck in an infinite loop?! But looking at the source for ZipInputStream.closeEntry() there doesn't seem to be any loops or anything suspicious there?

我还尝试使用 ZipFile 而不是 ZipInputStream 来提取 ZIP 存档,但随后出现以下错误:

I have also tried extracting the ZIP archive using ZipFile instead of ZipInputStream, but then I get the following error:

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

There is nothing wrong with the ZIP file, I have tested it with zip -v -T on Mac OSx. I have also tried re-zipping it using ZIP version 3.0 and 2.1 (original was 2.0). I can unzip all version without any problems on Mac OSx (using The Unarchiver and Archive Utility).

这让我发疯了,可能有什么问题?

This is driving me nuts, what can possibly be wrong?

 

更新(已解决)

事实证明这是一个非常愚蠢的问题,与解压无关.

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

也许这个帖子可以帮助犯同样愚蠢错误的其他人.

推荐答案

好吧,有时即使您关闭了所有先前的输出和输入流,您的 ZIP 提取代码也会卡住.而且,这是一个已知错误:ZipInputStream#read 可以返回 0.

Well, sometimes your ZIP extracting code can get stuck even if you closes all previous output and input streams. And, this is a known bug: ZipInputStream#read can return 0.

添加:

如果您的 ZIP 文件包含一些非 ACSII 文件名的文件,您将面临解压问题.Android 的 ZipInputStream 不适用于 UTF-8、CP437 等.

If your ZIP file contains some files with non-ACSII file names, you'll face problem with extracting. Android's ZipInputStream doesn't work well with UTF-8, CP437 and so on.

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

In that case Apache Commons should be a solution:

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

这篇关于使用 ZipInputStream 解压永远不会完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆