我们有一段代码可以在我们的系统上生成一个zip文件。一切都很好,但有时这个由FilZip或WinZip打开的zip文件被认为已损坏。
所以这是我的问题:如果生成的zip文件已损坏,我们如何以编程方式检查?
以下是我们用于生成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);
}
我们在这里做错了吗?
编辑: 实际上,上面的代码绝对没问题。我的问题是我正在为我的用户重定向错误的流。因此,不是打开一个zip文件,而是打开一些完全不同的东西。 Mea culpa :(
但主要问题仍然存在:如何以编程方式验证给定的zip文件是否未损坏?
答案 0 :(得分:28)
您可以使用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) {
}
}
}
答案 1 :(得分:9)
我知道它已经发布了一段时间,我已经使用了你们所有人提供的代码并提出了这个问题。这对于实际问题非常有用。检查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;
}
}
}
答案 2 :(得分:3)
我认为你会在zip文件生成期间看到对应的异常堆栈跟踪。所以,你可能不想增强你的异常处理。
答案 3 :(得分:2)
在我的实现中它看起来像那样。也许它会帮助你:
//[...]
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
答案 4 :(得分:1)
也许交换以下两行?;
fis.close();
zos.closeEntry();
我可以想象closeEntry()仍然会从流中读取一些数据。
答案 5 :(得分:1)
您的代码基本上没问题,尝试找出哪个文件负责损坏的zip文件。检查digitalFile.getFile()是否始终向FileInputStream返回有效且可访问的参数。只需在代码中添加一点日志记录,就会发现错误。
答案 6 :(得分:1)
new ZipFile(file)
再次压缩文件,重复工作,这不是你想要的。尽管只检查一个文件和问题压缩n文件。
看看这个:http://www.kodejava.org/examples/336.html
为您的zip创建校验和:
CheckedOutputStream checksum = new CheckedOutputStream(fos, new CRC32());
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(checksum));
...
当你完成压缩显示它
System.out.println("Checksum : " + checksum.getChecksum().getValue());
你必须使用java或其他工具读取zip,检查校验和是否匹配。
答案 7 :(得分:0)
ZipOutputStream does not close基础流。
您需要做的是:
FileOutputStream fos = new FileOutputStream(...);
ZipOutputStream zos = new ZipOutputStream(fos);
然后在你的结束区:
zos.close();
fos.flush(); // Can't remember whether this is necessary off the top of my head!
fos.close();