在Java中用于文件唯一性的哈希

时间:2009-11-23 21:56:23

标签: java hash

我正在尝试跟踪一组文件,这些文件可能具有相同的名称和元数据。我想使用哈希来区分并将其用作唯一ID,但我不确定使用哪一个?文件相对较小(在100 kb范围内),我希望能够在不到10秒的时间内对其进行散列。哪个哈希(Java 1.5中内置)最能满足我的需求?

4 个答案:

答案 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();
}
}