【问题标题】:Different ZipOutputStream results on different platforms不同平台上不同的 ZipOutputStream 结果
【发布时间】:2012-06-12 15:50:27
【问题描述】:

我有生成 zip 输出流的代码,然后我通过 servlet 的响应流发送该流。在我的 Mac 上进行开发测试时,一切正常,但是,当我将代码放在我的服务器 (RHEL) 上时,zip 存档似乎已损坏。当我尝试使用 jar 列出文件的内容时,我得到:

java.util.zip.ZipException:打开 zip 文件时出错

但奇怪的是,使用 jar 提取存档可以工作(但是其他解压缩器会失败)。

为了进一步测试,我确保 zip 文件的内容与来自我的 mac 和 RHEL 的内容完全相同。在这两种情况下,zip 文件的大小完全相同,但是哈希 (MD5) 不同。

正如我所说,生成 zip 文件的代码和内容完全相同,所以我不知道发生了什么。我相当确定我的 zip 文件创建是正确的,因为它在其中一个平台上工作。在 RHEL 服务器上生成 zip 文件时没有任何问题的迹象。

想法?感谢您的帮助。

编辑:这是代码...

// first add the kml document
ZipOutputStream stream = new ZipOutputStream(response.getOutputStream());
stream.putNextEntry(new ZipEntry("doc.kml"));
stream.write(kml.getBytes(), 0, kml.length());
stream.closeEntry();

File image = null;
byte[] bytes = null;
FileInputStream fstream = null;

// include the images for each type
File images = new File("/tmp/images");
String filename = null;

for(Type type: types) {
  filename = type.getName() + ".png";
  image = new File(images, filename);
  bytes = new byte[(int)image.length()];

  fstream = new FileInputStream(image);
  fstream.read(bytes);

  stream.putNextEntry(new ZipEntry(filename));
  stream.write(bytes);
  stream.closeEntry();

  fstream.close();
}

stream.finish();
stream.flush();
stream.close();

EDIT2:情节变厚了,只要存档中只有一个图像,似乎 RHEL zip 流就可以了。希望这足以让谷歌帮助我。

【问题讨论】:

  • 没有代码,很难给出太多反馈。我的 猜测 会是在某些时候数据被视为文本,也许您正在获得换行符转换。在客户端或服务器的任何时候,您使用的是 Readers 还是 Writers(可能在客户端下载代码)?
  • 只有内容不同,哈希才能不同。您关于“内容完全相同”的结论似乎没有根据。附加或附加到 zip 数据流中的垃圾字符可能会出现问题。想象一下,如果你有一个 HTML 标签,后面跟着一堆二进制 zip 数据。有些 zip 程序可以容忍这种垃圾,有些则不能。这可以解释为什么 jar 可以读取您的存档,而其他工具则不能。要对此进行诊断,请跟踪 HTTP 响应并直接查看 zip 内容。尝试只压缩一个文件而不压缩。
  • jtahlborn-我已更新帖子以包含代码。如果您有任何问题,请告诉我。 Cheeso-不确定要告诉你什么,当我使用 jar 解压缩文件时,它们确实是相同的哈希,但是,jar 文件本身不是相同的哈希。感谢您的帮助。

标签: java servlets stream zip


【解决方案1】:

几个问题:

  • 不要使用getBytes() 将字符串转换为字节。这将使用平台字符集,在不同的平台上可能会有所不同。始终使用 explicit 字符集,例如getBytes("UTF-8")。此外,getBytes() 返回的长度与字符串的长度无关。
  • 在读取文件时,不要将它们完全读入内存(这不会缩放)。使用固定大小的 byte[] 和 while 循环在 InputStream 和 OutputStream 之间进行复制。网上有数千个此代码的示例。 (或使用类似 commons io IOUtils.copy
  • 与上一点有关,InputStream.read() 有返回值,不要忽略。再次,您应该在您发现的任何示例中看到这一点,这些示例展示了将 InputStream 复制到 OutputStream 的最佳方式。

【讨论】:

  • 谢谢,你的子弹上有一些cmets:1)关于字符集的好点,我祈祷这可能是问题,2)同意,但我知道我在读什么,它们是静态文件并且很小,3)嗯,好的。如果字符集有帮助,我会报告。
  • @rjcarr - 意识到 getBytes 有另一个问题,正在更新我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
  • 2023-03-07
  • 2016-01-06
  • 2023-04-02
  • 1970-01-01
  • 2021-10-01
相关资源
最近更新 更多