0

我想散列(MD5)给定目录的所有文件,该目录包含 1000 张 2MB 照片。我尝试一次只运行一个 for 循环并散列一个文件,但这会导致内存问题。

我需要一种以有效方式(内存方面)散列每个文件的方法。

我已经发布了 3 个关于我的问题的问题,但现在我不想修复我的代码,而是想看看什么是满足我要求的最佳通用方法。

非常感谢你的帮助。

public class MD5 {

public static void main(String[] args) throws IOException {
    File file = new File("/Users/itaihay/Desktop/test");
    for (File f : file.listFiles()) {
        try {
            model.MD5.hash(f);
        } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.

        }
    }

private static MessageDigest md;
private static BufferedInputStream fis;
private static byte[] dataBytes;
private static byte[] mdbytes;

private static void clean() throws NoSuchAlgorithmException {
    md = MessageDigest.getInstance("MD5");
    dataBytes = new byte[8192];
}
public static void hash(File file) {
    try {
        clean();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    try {
        fis = new BufferedInputStream(new FileInputStream(file));
        int nread = 0;
        while ((nread = fis.read(dataBytes)) != -1) {
            md.update(dataBytes, 0, nread);
        }
        nread = 0;
        mdbytes = md.digest();  System.out.println(javax.xml.bind.DatatypeConverter.printHexBinary(mdbytes).toLowerCase());

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fis.close();
            dataBytes = null;
            md = null;
            mdbytes = null;
        } catch (IOException e) {
            e.printStackTrace();
      }       
    }
  }
}
4

3 回答 3

1

正如其他人所说,使用内置的 Java MD5 代码,您应该能够保持非常小的内存占用。在散列大量 Jar 文件(每个文件最多几 MB,通常一次价值 500MB)并获得不错的性能时,我会做类似的事情。您肯定会想尝试不同的缓冲区大小,直到找到适合您的系统配置的最佳大小。以下代码片段一次使用不超过bufSize+128字节,加上用于计算 md5 哈希的 、 和 对象FileMessageDigest开销可以忽略不计:InputStream

InputStream is = null;
File f = ...
int bufSize = ...
byte[] md5sum = null;

try {
    MessageDigest digest = MessageDigest.getInstance("MD5");
    is = new FileInputStream(f);
    byte[] buffer = new byte[bufSize];

    int read = 0;
    while((read = is.read(buffer)) > 0) digest.update(buffer,0,read);
    md5sum = digest.digest();
} catch (Exception e){
} finally {
    try{
        if(is != null) is.close();
    } catch (IOException e){}
}
于 2013-09-12T18:18:00.910 回答
0

MD5 以 64 字节块更新其状态,因此您一次只需要 16 字节的文件在内存中。MD5 状态本身是 128 位,输出大小也是如此。

最保守的内存方法是一次从每个文件读取 64 个字节,逐个文件,并使用它来更新该文件的 MD5 状态。您最多需要 999 * 16 + 64 = 16048 ~= 16k 的内存。

但是如此小的读取效率会非常低,因此您可以从那里增加文件的读取大小以适应您的内存限制。

于 2013-09-12T18:04:37.563 回答
0

增加 Java 堆空间可以在短期内解决它。

从长远来看,您希望研究将图像读取到可以放入内存的固定大小的队列中。不要一次全部读完。将最近的图像加入队列,将最早的图像出队。

于 2013-09-12T18:01:18.357 回答