import java.io.File
import java.io.FileInputStream
import java.math.BigInteger
import java.security.MessageDigest
import java.util.HashMap
import java.util.Map
public class FileDigest {
/**
* 获取单个文件的MD5值!
* @param file
* @return
*/
public static String getFileMD5(File file) {
if (!file.isFile()){
return null
}
MessageDigest digest = null
FileInputStream in=null
byte buffer[] = new byte[1024]
int len
try {
digest = MessageDigest.getInstance("MD5")
in = new FileInputStream(file)
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len)
}
in.close()
} catch (Exception e) {
e.printStackTrace()
return null
}
BigInteger bigInt = new BigInteger(1, digest.digest())
return bigInt.toString(16)
}
/**
* 获取文件夹中文件的MD5值
* @param file
* @param listChild true递归子目录中的文件
* @return
*/
public static Map<String, String>getDirMD5(File file,boolean listChild) {
if(!file.isDirectory()){
return null
}
//<filepath,md5>
Map<String, String>map=new HashMap<String, String>()
String md5
File files[]=file.listFiles()
for(int i=0i<files.lengthi++){
File f=files[i]
if(f.isDirectory()&&listChild){
map.putAll(getDirMD5(f, listChild))
} else {
md5=getFileMD5(f)
if(md5!=null){
map.put(f.getPath(), md5)
}
}
}
return map
}
public static void main(String[] args) {
File file1 = new File("a.txt")
File file2 = new File("b.txt")
System.out.println(getFileMD5(file1).equals(getFileMD5(file2)))
}
}
不同内容得出相同MD5值,虽然概率低,但总是不放心。如果在已知文件编码范围的条件下,找到MD5绝对区分长度范围(即:该范围内取样内容的MD5相同的,内容保证相同;绝不存在不同内容得出相同MD5值的现象),那么,可按合理的长度分片、按一定顺序遍历整个文件(属性信息、头部、尾部、同步随机点、其他),比较MD5,一旦有异立即判定文件不同,终止比较。这种分片取样比较MD5的思路可能快于逐字节比较也绝对可信要确保 100%正确就必须校验全文,通过以上思路来比较,即是。
(注:
其他据说相对于MD5来讲不易碰撞(即不同内容得出相同MD5值的概率可能更低)的算法推荐:起码 SHA1 ,最好 SHA256、 SHA512、MD5+CRC32、HMAC,或者几种不同类型算法的同步进行。
在精通算法的情况下,将这里推荐的算法取代上文中提到的MD5来考量,能扩大绝对区分长度范围,可能更方便更快的比较。
但是又有这样的考虑:逐字节比较的算法最简单,算法弄复杂了反而会增加额余的时间;逐字节比较的算法也可以放到上文中来考量,进行同步取样和各种遍历的顺序与方式,说不定,在保证100%的可信度的条件下,逐字比较反而最快呢?
我觉得时间的耗费关键处在于,所有的算法,都要将两个位于不同区域或载体的文件的同位区域收集到一起进行比较,这个收集花费时间Ta(i),与取样长度、存储区域或载体等相关;{如果要将文件取很大一部或全部读入内存,然后再逐一集中比较,则会减小以上的Ta(i),而增加一个额外读入的时间Tc(i)*次数M(i)}。比较的次数大致为N(i);而如果在一个文件中顺序读取一个区域并且计算它的某个整体评定值,这个花费的时间为Tb(i),与取样长度、计算程序、设备性能等相关。
总体的比较时间大致是Ta(i)*N(i)*Tb(i)+{Tc(i)*M(i)}
逐字节比较,其中Tb(i)、Ta(i)都是最短的,但是N(i)最大,
总之,可以设计不同的算法,通过实际环境和文件的检测,来决定采用何种算法。
)
外一则:
两个取样内容, MD5等算法的计算值 不同,则内容一定不同; 计算值相同,则 内容可能相同,但可能性是否达到100%,内容相同的概率是多少,根据编码范围、算法来确定。如果是比较一个文件和许多其他文件是否相同,并且提前知道其他文件的 MD5 值,可先比较 MD5 值可以大大提高文件比较的速度。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)