我有相同的要求,并选择我的’目录哈希’作为目录中所有(非目录)文件的连接流的MD5哈希.正如Crozin在
a similar question的评论中提到的,您可以使用SequenceInputStream充当连接其他流的负载的流.我使用
Apache Commons Codec作为MD5算法.
基本上,您通过目录树递归,将FileInputStream实例添加到Vector以获取非目录文件. Vector然后方便地使用elements()方法来提供SequenceInputStream需要循环的Enumeration.对于MD5算法,它只显示为一个InputStream.
一个问题是,每次哈希与相同输入相同时,您需要以相同顺序呈现的文件. File中的listFiles()方法不保证排序,因此我按文件名排序.
我正在为SVN控制的文件做这个,并且想避免散列隐藏的SVN文件,所以我实现了一个标志以避免隐藏文件.
相关基本代码如下. (显然它可以’硬化’.)
import org.apache.commons.codec.digest.DigestUtils;
import java.io.*;
import java.util.*;
public String calcMD5HashForDir(File dirToHash, boolean includeHiddenFiles) {
assert (dirToHash.isDirectory());
Vector fileStreams = new Vector();
System.out.println("Found files for hashing:");
collectInputStreams(dirToHash, fileStreams, includeHiddenFiles);
SequenceInputStream seqStream =
new SequenceInputStream(fileStreams.elements());
try {
String md5Hash = DigestUtils.md5Hex(seqStream);
seqStream.close();
return md5Hash;
}
catch (IOException e) {
throw new RuntimeException("Error reading files to hash in "
+ dirToHash.getAbsolutePath(), e);
}
}
private void collectInputStreams(File dir,
List foundStreams,
boolean includeHiddenFiles) {
File[] fileList = dir.listFiles();
Arrays.sort(fileList, // Need in reproducible order
new Comparator() {
public int compare(File f1, File f2) {
return f1.getName().compareTo(f2.getName());
}
});
for (File f : fileList) {
if (!includeHiddenFiles && f.getName().startsWith(".")) {
// Skip it
}
else if (f.isDirectory()) {
collectInputStreams(f, foundStreams, includeHiddenFiles);
}
else {
try {
System.out.println("\t" + f.getAbsolutePath());
foundStreams.add(new FileInputStream(f));
}
catch (FileNotFoundException e) {
throw new AssertionError(e.getMessage()
+ ": file should never not be found!");
}
}
}
}