Java 如何检查生成的 zip 文件是否已损坏?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2085637/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if a generated zip file is corrupted?
提问by Kico Lobo
we have a piece of code which generates a zip file on our system. Everything is ok, but sometimes this zip file while opened by FilZip or WinZip is considered to be corrupted.
我们有一段代码可以在我们的系统上生成一个 zip 文件。一切正常,但有时这个 zip 文件在由 FilZip 或 WinZip 打开时被认为已损坏。
So here is my question: how can we check programatically if a generated zip file is corrupted?
所以这是我的问题:我们如何以编程方式检查生成的 zip 文件是否已损坏?
Here is the code we are using to generate our zip files:
这是我们用来生成 zip 文件的代码:
try {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(tmpFile));
byte[] buffer = new byte[16384];
int contador = -1;
for (DigitalFile digitalFile : document.getDigitalFiles().getContent()) {
ZipEntry entry = new ZipEntry(digitalFile.getName());
FileInputStream fis = new FileInputStream(digitalFile.getFile());
try {
zos.putNextEntry(entry);
while ((counter = fis.read(buffer)) != -1) {
zos.write(buffer, 0, counter);
}
fis.close();
zos.closeEntry();
} catch (IOException ex) {
throw new OurException("It was not possible to read this file " + arquivo.getId());
}
}
try {
zos.close();
} catch (IOException ex) {
throw new OurException("We couldn't close this stream", ex);
}
Is there anything we are doing wrong here?
我们在这里做错了什么吗?
EDIT: Actually, the code above is absolutely ok. My problem was that I was redirecting the WRONG stream for my users. So, instead of opening a zip file they where opening something completely different. Mea culpa :(
编辑:实际上,上面的代码绝对没问题。我的问题是我为我的用户重定向了错误的流。因此,不是打开 zip 文件,而是打开完全不同的东西。我的罪过:(
BUT the main question remains: how programatically I can verify if a given zip file is not corrupted?
但主要问题仍然存在:我如何以编程方式验证给定的 zip 文件是否未损坏?
采纳答案by Arnaud
You can use the ZipFile
class to check your file :
您可以使用ZipFile
该类来检查您的文件:
static boolean isValid(final File file) {
ZipFile zipfile = null;
try {
zipfile = new ZipFile(file);
return true;
} catch (IOException e) {
return false;
} finally {
try {
if (zipfile != null) {
zipfile.close();
zipfile = null;
}
} catch (IOException e) {
}
}
}
回答by John Doe
I think you'll see correspondent exception stack trace during zip-file generation. So, you probably wan't to enhance your exception handling.
我认为您会在 zip 文件生成期间看到相应的异常堆栈跟踪。因此,您可能不想增强异常处理。
回答by John Doe
ZipOutputStream does not closethe underlying stream.
ZipOutputStream不会关闭底层流。
What you need to do is:
你需要做的是:
FileOutputStream fos = new FileOutputStream(...);
ZipOutputStream zos = new ZipOutputStream(fos);
Then in your closing block:
然后在你的结束块中:
zos.close();
fos.flush(); // Can't remember whether this is necessary off the top of my head!
fos.close();
回答by Waverick
Perhaps swap the following two lines?;
也许交换以下两行?
fis.close();
zos.closeEntry();
I can imagine that the closeEntry() will still read some data from the stream.
我可以想象 closeEntry() 仍然会从流中读取一些数据。
回答by stacker
Your code is basically OK, try to find out which file is responsible for the corrupted zip file. Check whether digitalFile.getFile() always returns a valid and accessible argument to FileInputStream. Just add a bit logging to your code and you will find out what's wrong.
你的代码基本没问题,试着找出哪个文件对损坏的zip文件负责。检查 digitalFile.getFile() 是否始终向 FileInputStream 返回有效且可访问的参数。只需在您的代码中添加一些日志记录,您就会发现问题所在。
回答by S?ren
in my implementation it looks like that. maybe it helps you:
在我的实现中,它看起来像那样。也许它可以帮助你:
//[...]
try {
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
zos.putNextEntry(new ZipEntry(file.getName()));
try {
final byte[] buf = new byte[BUFFER_SIZE];
while (true) {
final int len = bis.read(buf);
if (len == -1) {
break;
}
zos.write(buf, 0, len);
}
zos.flush();
zos.closeEntry();
} finally {
try {
bis.close();
} catch (IOException e) {
LOG.debug("Buffered Stream closing failed");
} finally {
fis.close();
}
}
} catch (IOException e) {
throw new Exception(e);
}
//[...]
zos.close
回答by albfan
new ZipFile(file)
compress again the file, so duplicate efforts and that is not what you are looking for. Despite of the fact that only check one file and the question compress n-files.
再次压缩文件,因此重复工作,这不是您要查找的内容。尽管仅检查一个文件并且问题压缩 n 个文件这一事实。
Take a look to this: http://www.kodejava.org/examples/336.html
看看这个:http: //www.kodejava.org/examples/336.html
Create a checksum for your zip:
为您的 zip 创建校验和:
CheckedOutputStream checksum = new CheckedOutputStream(fos, new CRC32());
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(checksum));
...
And when you finish the compression show it
当你完成压缩显示它
System.out.println("Checksum : " + checksum.getChecksum().getValue());
You must do the same reading the zip with java or others tools checking if checksums match.
您必须使用 java 或其他工具检查校验和是否匹配来读取 zip。
see https://stackoverflow.com/a/10689488/848072for more information
回答by user1707141
I know its been a while that this has been posted, I have used the code that all of you provided and came up with this. This is working great for the actual question. Checking if the zip file is corrupted or not
我知道这已经发布了一段时间,我已经使用了你们所有人提供的代码并想出了这个。这对于实际问题非常有用。检查 zip 文件是否损坏
private boolean isValid(File file) {
ZipFile zipfile = null;
ZipInputStream zis = null;
try {
zipfile = new ZipFile(file);
zis = new ZipInputStream(new FileInputStream(file));
ZipEntry ze = zis.getNextEntry();
if(ze == null) {
return false;
}
while(ze != null) {
// if it throws an exception fetching any of the following then we know the file is corrupted.
zipfile.getInputStream(ze);
ze.getCrc();
ze.getCompressedSize();
ze.getName();
ze = zis.getNextEntry();
}
return true;
} catch (ZipException e) {
return false;
} catch (IOException e) {
return false;
} finally {
try {
if (zipfile != null) {
zipfile.close();
zipfile = null;
}
} catch (IOException e) {
return false;
} try {
if (zis != null) {
zis.close();
zis = null;
}
} catch (IOException e) {
return false;
}
}
}