2011-06-17 91 views
8

我正在做一些图像处理代码,其中我从URL下载一些图像(作为BufferedImage)并将其传递给图像处理器。要检查两个图像文件是否相同..Checksum或哈希?

我想避免多次向图像处理器传递相同的图像(因为图像处理操作的成本很高)。图像的URL结束点(如果它们是相同的图像)可能会有所不同,因此我可以通过该URL防止出现这种情况。所以我打算做一个校验和或散列来确定代码是否再次遇到相同的图像。

对于md5,我尝试了Fast MD5,它为图像生成了20K +字符长度的十六进制校验和值(某些示例)。当涉及到数据库存储时,显然存储这个20K字符散列值将成为一个问题。因此我尝试了CRC32(来自java.util.zip.CRC32)。它确实生成了比哈希小得多的长度校验和。

我明白校验和和散列是出于不同的目的。为了上面解释的目的,我可以使用CRC32吗?它会解决目的还是我不得不尝试比这两个更多的东西?

谢谢, 阿比

+1

[校验和散列和是相同的(http://en.wikipedia.org/wiki/Checksum)。其实你只是看看不同的算法。 – 2011-06-17 06:33:15

+1

128位MD5哈希值应该足够您的目的。 – Thor 2011-06-17 06:35:08

+5

顺便说一句 - MD5应该创建一个128位散列值,而crc32有32位......你做了什么来产生20k +长度的十六进制校验和? – 2011-06-17 06:35:10

回答

1

校验和散列基本上是相同的。你应该能够计算任何种类的散列。一般的MD5通常就足够了。如果你喜欢,你可以存储大小和md5散列(我认为它是16字节)。

如果两个文件有不同的大小,它们是不同的文件。你甚至不需要计算数据散列。如果您不太可能拥有许多重复文件,并且文件类型较大(例如,使用相机拍摄的JPG照片),则此优化可能会让您花费大量时间。

如果两个或多个文件的大小相同,则可以计算散列并进行比较。

如果两个散列值相同,则可以比较实际数据,看看它是否完全不同。这是非常非常不可能的,但理论上是可能的。您的散列值越大(md5为16个字节,而CR32只有4个),两个不同文件将具有相同散列的可能性越小。 虽然只需要10分钟的编程来执行这个额外的检查,所以我会说:比对不起更安全。 :)

若要进一步优化此功能,只要两个文件具有相同的大小,就可以比较它们的数据。无论如何你需要阅读这些文件来计算它们的哈希,所以为什么不直接比较它们,只要它们是具有特定大小的唯一两个。

+0

也许可能存在一个问题,即将已处理的文件与新文件进行比较。校验和或散列占用的空间更少 – SJuan76 2011-06-17 06:55:03

+0

这是真的,我从来没有把整个文件存储在数据库中进行比较,只是说一次运行就不需要计算散列值。存储数据以检查新添加的文件,那么存储哈希值或者可以选择仅存储文件大小是有意义的,并且只有在两个文件大小相同的情况下才计算(并存储)哈希值es匹配。这将节省空间,并节省磁盘IO。 – GolezTrol 2011-06-17 07:48:16

5

CRC和MD5之间的区别在于,篡改文件以匹配“目标”MD5比篡改文件以匹配“目标”校验和更困难。由于这对您的程序来说似乎没有问题,因此您使用哪种方法应该没有关系。也许MD5可能会占用更多的CPU资源,但我不知道这种不同会有什么关系。

主要问题应该是摘要的字节数。

如果你正在做一个整数校验和将意味着,对于一个2K大小的文件,你将2^2048个组合适合2^32个组合 - >对于每个CRC值,你将有2^64可能匹配它的文件。如果你有一个128位的MD5,那么你有2^16个可能的冲突。

您计算的代码越大,碰撞的可能性越小(因为计算得到的代码均匀分布),所以比较安全。

总之,为了minimice可能出现的错误,我想第一个分类应使用文件大小......先比较文件的大小,如果他们匹配,则比较校验/哈希值。

-3

用于比较两个图像缓冲可以使用BufferedImage.equals()为简单起见,你可以使用BufferedImage.hashCode()来获得图像的哈希值,这是快速和快速。

+6

'equals()'和'hashCode()'都回退到默认的'Object'实现,不能用来比较'BufferedImage'的两个不同实例 – 2011-12-20 23:49:46