使用ZipInputStream解压缩永远不会完成(Unzipping with ZipInputStream never finishes)

编程入门 行业动态 更新时间:2024-10-24 11:19:48
使用ZipInputStream解压缩永远不会完成(Unzipping with ZipInputStream never finishes)

我正在使用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() ,调试器只是“消失”,即下一行( 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)。

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

更新(已解决)

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

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

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

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

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?

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

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?

 

Update (solved)

Turns out to be a really stupid problem, not really related to the unzipping.

I'm downloading the ZIP files from a server before unzipping them, and apparently I forgot to call close() on the output stream from the download operation before starting the unzip operation.

Perhaps this thread can help someone else who makes the same stupid mistake.

最满意答案

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

加成:

如果您的ZIP文件包含一些具有非ACSII文件名的文件,则您将面临解压缩问题。 Android的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; }

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.

Addition:

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.

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

更多推荐

本文发布于:2023-07-16 07:39:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1125504.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:永远不会   解压缩   ZipInputStream   Unzipping   finishes

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!