为什么我的java.util.zip函数显示不一致的行为?

时间:2011-01-28 19:30:36

标签: java zip

我有一个Java应用程序,它使用java.util.zip库来压缩和解压缩文件。我所拥有的是服务器上的zip文件(由我的应用程序创建)和客户端压缩他的一些文件并将文件上传到服务器,但如果底层文件没有区别,那么我不想浪费上传时间。我想我可以计算客户端和服务器端的MD5哈希值并查看它们是否相同,但发生的事情是我使用我的应用程序解压缩zip文件,然后不更改任何底层文件,我使用我的应用程序重新压缩它,但旧的和新的zip文件有不同的MD5哈希。有没有人知道为什么会这样,如果有更好的方法来比较两个zip文件?感谢。

5 个答案:

答案 0 :(得分:3)

更糟糕的是,我认为:

执行两次相同的zip操作可能会产生两种不同的zip存档:

> zip some.zip some.txt 
  adding: some.txt (stored 0%)
> zip other.zip some.txt
  adding: some.txt (stored 0%)
> ll
total 24
-rw-r--r--  1 cthies  staff  170 12 Dez 18:01 other.zip
-rw-r--r--  1 cthies  staff    4 12 Dez 18:01 some.txt
-rw-r--r--  1 cthies  staff  170 12 Dez 18:01 some.zip
> md5 *.zip
MD5 (other.zip) = f56d7753c5af78427274d930b9fb8c90
MD5 (some.zip) = e2f0382c4ad31871f62fb559157df8e8

查看二进制文件,只能在一个地方看到差异:

> xxd some.zip > some.xxd
> xxd other.zip > other.xxd
> colordiff *.xxd
3c3
< 0000020: 6d65 2e74 7874 5554 0900 0363 33e6 4e78  me.txtUT...c3.Nx
---
> 0000020: 6d65 2e74 7874 5554 0900 0363 33e6 4e64  me.txtUT...c3.Nd

我认为(取决于zip-app本身)可以/将涉及当前的系统时间。因此,任何zip操作 - 在完全相同的源上 - 都可以(!)是唯一的,因此不能假设校验和相等。

我发现与时间无关的工具: tar 7z 。 (两个命令行) 即 tar 7z 以相等的校验和(md5)复制档案。

(使用命令行zip实用程序在OSX 10.6.8上测试)

答案 1 :(得分:1)

在黑暗中只是一个疯狂的镜头 - 你在不同的情况下计算你的哈希值的两个文件系统?

也就是说,其中一个是Windows,它将ABC.CLASS和abc.class文件名视为相同,是一个将ABC.CLASS和abc.class视为不同的Unix变体之一?

只是猜测......

编辑:您还可以查看嵌入式目录分隔符/ \。或者:在zip文件中。

答案 2 :(得分:1)

1)检查文件的时间戳。由unziping生成的文件可能具有不同的上次修改日期和/或创建日期。该文件元数据可能用于创建哈希值。

2)您是否在两个系统上使用相同的操作系统?如果操作系统不同,则可能使用不同的字符编码。

3)你能区分zip文件吗?不同的MD5哈希应该表示不同的数据。它会很混乱但你可能会通过比较原始文件获得一些线索。

答案 3 :(得分:0)

您无法比较不同zip程序中生成的zip文件,并且期望它们完全相同,即使在压缩之前使用了完全相同的文件。

拉链文件不保证在两种不同的zip编码实现之间是确定性的。 Zip的工作原理是将重复的数据部分替换为查找键的数量。两种不同的算法可以不同地确定字典(重复数据集),以努力优化压缩级别。然而,这两种实现都可以创建有效的zip文件,当解压缩时会生成相同的文件。

唯一可行的方法是保证在两种情况下都使用完全相同的zip算法。

编辑:这就是你在Deflate算法的http://download.oracle.com/javase/1.5.0/docs/api/java/util/zip/Deflater.html

的Java实现中看到不同压缩级别设置的原因

答案 4 :(得分:-2)

你正在写一个新文件,而不是同一个文件,所以MD5会改变,因为我从这样的线程中理解它: MD5 Hash Not Reversible