【问题标题】:Get File Hash Performance/Optimization获取文件哈希性能/优化
【发布时间】:2013-04-02 16:56:35
【问题描述】:

我正在尝试尽快获取文件的哈希值。我有一个程序可以散列大量数据(100GB+),包括随机文件大小(每个文件从几 KB 到 5GB+),从少量文件到几十万个文件。

程序必须支持所有 Java 支持的算法(MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512)。

目前我使用:

/**
 * Gets Hash of file.
 * 
 * @param file String path + filename of file to get hash.
 * @param hashAlgo Hash algorithm to use. <br/>
 *     Supported algorithms are: <br/>
 *     MD2, MD5 <br/>
 *     SHA-1 <br/>
 *     SHA-256, SHA-384, SHA-512
 * @return String value of hash. (Variable length dependent on hash algorithm used)
 * @throws IOException If file is invalid.
 * @throws HashTypeException If no supported or valid hash algorithm was found.
 */
public String getHash(String file, String hashAlgo) throws IOException, HashTypeException {
    StringBuffer hexString = null;
    try {
        MessageDigest md = MessageDigest.getInstance(validateHashType(hashAlgo));
        FileInputStream fis = new FileInputStream(file);

        byte[] dataBytes = new byte[1024];

        int nread = 0;
        while ((nread = fis.read(dataBytes)) != -1) {
            md.update(dataBytes, 0, nread);
        }
        fis.close();
        byte[] mdbytes = md.digest();

        hexString = new StringBuffer();
        for (int i = 0; i < mdbytes.length; i++) {
            hexString.append(Integer.toHexString((0xFF & mdbytes[i])));
        }

        return hexString.toString();

    } catch (NoSuchAlgorithmException | HashTypeException e) {
        throw new HashTypeException("Unsuppored Hash Algorithm.", e);
    }
}

有没有更优化的方法来获取文件哈希?我正在寻找极致性能,但不确定我是否已经做到了最好的方式。

【问题讨论】:

  • 你分析过代码吗?它大部分时间都在哪里度过?

标签: java algorithm file hash


【解决方案1】:

我看到了许多潜在的性能改进。一种是用StringBuilder代替StringBuffer;它是源兼容的,但性能更高,因为它是不同步的。第二个(更重要的)是使用FileChanneljava.nio API 而不是FileInputStream——或者至少将FileInputStream 包装在BufferedInputStream 中以优化I/O。

【讨论】:

    【解决方案2】:

    除了欧内斯特的回答:- MessageDigest.getInstance(validateHashType(hashAlgo)) 我认为这可以缓存在以 validateHashType(hashAlgo) 为键的线程本地哈希图中。制作 MessageDigest 需要时间,但您可以重用它们:从 Map 获取实例后,在开始时调用 reset() 方法。

    查看 java.lang.ThreadLocal 的 javadoc

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-22
      • 2019-02-15
      • 1970-01-01
      • 1970-01-01
      • 2021-05-21
      • 1970-01-01
      相关资源
      最近更新 更多