我正在尝试跟踪一组文件,这些文件可能具有相同的名称和元数据。我想使用哈希来区分并将其用作唯一ID,但我不确定使用哪一个?文件相对较小(在100 kb范围内),我希望能够在不到10秒的时间内对其进行散列。哪个哈希(Java 1.5中内置)最能满足我的需求?
答案 0 :(得分:15)
请注意,这种哈希值从不是唯一的,但如果使用有效的哈希,你很有可能永远不会发生冲突。
如果你不关心安全性(即有人故意试图破解你的哈希),那么只需使用MD5哈希就可以轻松地为你提供优秀的哈希值。
虽然SHA-1在理论上仍有缺陷,但它可能会在不到10秒的时间内完成100Kb的SHA散列,但它的强度要高于MD5。
MessageDigest将为您提供实现。
以下是一些examples of using it with streams。
另外我应该注意this excellent answer from jarnbjo 表明即使在相对适中的x86硬件上,即使是Java中提供的SHA散列也能够超过20MB / s。这意味着100KB(内存中)输入数据的 5-10毫秒级别性能,因此您的目标不到10秒就会大大高估所涉及的工作量。您可能完全受限于从磁盘读取文件的速率,而不是您使用的任何散列算法。
如果您需要强大加密哈希,您应该在问题中指出这一点。即使这样,除非你希望使用像Bouncy Castle之类的外部库,否则一些1以上的SHA仍然是你最好的选择,因为如果存在完善的实现,你绝不应该尝试使用自己的加密。
对于一些合理有效的示例代码,我建议this how to 其中的突出点可以被提炼为以下内容(根据您的需要调整缓冲区大小):
import java.io.*;
import java.security.MessageDigest;
public class Checksum
{
const string Algorithm = "SHA-1"; // or MD5 etc.
public static byte[] createChecksum(String filename) throws
Exception
{
InputStream fis = new FileInputStream(filename);
try
{
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do
{
numRead = fis.read(buffer);
if (numRead > 0)
{
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
return complete.digest();
}
finally
{
fis.close();
}
}
}
答案 1 :(得分:5)
您可以将MessageDigest与 SHA1 :
一起使用 MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
InputStream is = new FileInputStream(aFile);
int res;
while ((res = inputStream.read()) != -1) {
digester.update((byte) res);
}
byte[] digest = messageDigest.digest();
答案 2 :(得分:0)
使用基于内容的散列SHA1是我使用的。 MD5更弱更快,但在现代处理器上,速度并不是一个问题。
答案 3 :(得分:0)
这是我的方式, 我认为这应该很快,检查它是否在10秒内完成
package utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* This class used to compute the hash value of any string
*/
public class MyHasher {
private static final String ALGORITHM = "MD5";
static MessageDigest md = null;
static{
try {
md = MessageDigest.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e) {
MyLogger.error("Can't find implementation of "+ALGORITHM+" algorithm", e);
}
}
/**
* Compute hash value of any string
* @param arg the string to compute hash value of.
* @return the hex hash value as a string.
*/
public static String getHash(String arg) {
md.update(arg.getBytes());
byte[] hashValue = md.digest();
return convertToHex(hashValue);
}
/**
* Converts byte array to the human readable string of hex'es
* @param data the byte array to convert
* @return string representation of the hex'es of the byte array
*/
public static String convertToHex(byte[] data){
StringBuffer buf = new StringBuffer();
for(int i=0;i<data.length;i++){
int halfbyte = (data[i]>>>3)&0x0F;
int two_halfs = 0;
do{
if((0<=halfbyte) && (halfbyte <=9))
buf.append((char) ('0'+halfbyte));
else
buf.append((char) ('a'+(halfbyte-10)));
halfbyte = data[i] & 0x0F;
}while(two_halfs++ <1);
}
return buf.toString();
}
}