2009-11-23 27 views
5

Tôi đang cố gắng theo dõi tập hợp các tệp có thể có cùng tên và siêu dữ liệu. Tôi muốn sử dụng hàm băm để phân biệt và sử dụng nó làm một ID duy nhất, nhưng tôi không chắc chắn nên sử dụng mã nào? Các tệp tương đối nhỏ (trong phạm vi 100 kb) và tôi muốn có thể băm trong vòng chưa đầy 10 giây. Mà băm (mà đi kèm được xây dựng trong Java 1.5) sẽ tốt nhất bộ nhu cầu của tôi?Băm nào để sử dụng cho tính duy nhất của tệp trong Java

Trả lời

15

Lưu ý rằng một băm thuộc loại này sẽ không bao giờ là duy nhất, với việc sử dụng hiệu quả, bạn có cơ hội rất tốt để không bao giờ gặp va chạm.

Nếu bạn không quan tâm đến bảo mật (nghĩa là ai đó cố tình bẻ khóa băm của bạn) thì chỉ cần sử dụng hàm băm MD5 sẽ cho bạn một băm tuyệt vời với nỗ lực tối thiểu.

Có khả năng bạn có thể thực hiện hàm băm SHA 100Kb trong vòng chưa đầy 10 giây và mặc dù SHA-1 vẫn còn thiếu sót về mặt lý thuyết, nó có cường độ cao hơn MD5.

MessageDigest cũng sẽ giúp bạn triển khai.

Dưới đây là một số examples of using it with streams.

Ngoài ra tôi nên lưu ý rằng this excellent answer from jarnbjo sẽ cho biết rằng thậm chí SHA băm được cung cấp trong Java cũng có khả năng vượt quá 20MB/s ngay cả trên phần cứng x86 tương đối khiêm tốn. Điều này sẽ ngụ ý 5-10 mili giây hiệu suất cấp trên 100KB (trong bộ nhớ) dữ liệu đầu vào để mục tiêu của bạn dưới 10 giây là giá trị lớn nhất của nỗ lực liên quan. Có thể bạn sẽ hoàn toàn bị giới hạn bởi tốc độ bạn có thể đọc các tệp từ đĩa thay vì bất kỳ thuật toán băm nào mà bạn sử dụng.

Nếu bạn cần mạnh băm mật mã, bạn nên biểu thị điều này trong câu hỏi. Ngay cả sau đó SHA của một số hương vị trên 1 vẫn có thể là đặt cược tốt nhất của bạn trừ khi bạn muốn sử dụng một thư viện bên ngoài như Bouncy Castle vì bạn không bao giờ nên cố gắng để cuộn mật mã của riêng bạn nếu một thực hiện cũng được thành lập tồn tại.

Đối với một số mẫu mã hợp lý có hiệu quả tôi đề nghị this how to Những điểm nổi bật trong số đó có thể được cất vào sau (điều chỉnh kích thước bộ đệm như bạn thấy phù hợp):

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

+1 cho ghi chú rằng băm sẽ không bao giờ là duy nhất. – PSpeed

+0

Câu trả lời tuyệt vời tất cả xung quanh, cảm ơn. –

0

sử dụng hàm băm SHA1 dựa trên nội dung là những gì tôi sử dụng. MD5 yếu hơn và nhanh hơn nhưng tốc độ xử lý hiện đại không phải là mối quan tâm.

5

bạn có thể sử dụng MessageDigest với 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(); 
+0

@ downvoter: hãy giải thích downvote của bạn hoặc nó là vô nghĩa – dfa

+0

không có đầu mối, nhưng đó là một câu trả lời hợp lý vì vậy đây là một +1 để bù đắp – ShuggyCoUk

0

đây là cách tôi làm điều đó, tôi nghĩ rằng điều này sẽ làm việc nhanh chóng, kiểm tra nếu nó hoàn thành trong vòng 10 giây

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(); 
} 
} 
+0

Tôi sẽ thêm điều kiện này buộc toàn bộ tập tin được đọc vào bộ nhớ thông qua một chuỗi có thể không hiệu quả, yêu cầu nhiều bộ nhớ hơn mức cần thiết và có ý nghĩa nếu bạn muốn băm một byte thô ascii thô hơn là buộc nó trở thành ký tự rộng đầu tiên (nếu bạn muốn có một công cụ chuẩn bên ngoài để có thể băm nó) – ShuggyCoUk

Các vấn đề liên quan