我正在尝试编写一个函数来递归获取目录中所有文件的md5sum,但是每次运行时都会得到不同的结果而没有修改任何文件。
代码我从以下方面得到了这些结果:
var crypto = require('crypto');
var fs = require('fs');
var path = require('path');
function _deepMD5(dir, md5){
var files = fs.readdirSync(dir);
for(var i = 0; i < files.length; i++){
var fp = dir+path.sep+files[i];
if(fs.lstatSync(fp).isDirectory()){
_deepMD5(fp, md5);
}
else{
var fh = fs.openSync(fp, 'r');
var chunkSize=1024;
var buffer=new Buffer(chunkSize, 'binary');
while(fs.readSync(fh, buffer, 0, chunkSize, null) != 0){
md5.update(buffer);
}
}
}
}
function deepMD5(dir){
var md5sum = crypto.createHash('md5');
_deepMD5(dir, md5sum);
return md5sum.digest('hex');
}
console.log(deepMD5("."));
答案 0 :(得分:2)
创建新缓冲区时,不会清除它。所以你从随机填充的缓冲区开始 - 这是运行之间的变化来自。
接下来,您读取1024个字节并使用它更新哈希值。但是,该读取实际上读取最多 1024字节。它返回实际读取的字节数。你会想要意识到这一点。否则,每次你通过一个不能被1024字节整除的文件时,你会在最后用额外的东西更新哈希值(如果是第一次读取,则是随机的,或者是先前读取的剩余内容。
因此,每当读取少于chunkSize
个字节时,您希望切掉实际来自最近读取的字节并将该缓冲区传递给update
:
var length;
while((length = fs.readSync(fh, buffer, 0, chunkSize, null)) != 0){
if(length == chunkSize)
md5.update(buffer);
else
md5.update(buffer.slice(0, length));
}
为了效率,我在没有必要时避免切片。当然,如果您更喜欢较短的代码并且不担心性能,您可以随时进行切片。
答案 1 :(得分:1)
您的代码需要进行非常小的更改才能使其按预期工作:您需要在创建后使用buffer.fill(0)
重置新缓冲区。
new Buffer()
表达式分配内存但不清理,因此您必须手动执行此操作。如果您的所有文件都超过1024字节大小,您可能不会注意到该问题。但是,如果至少有一个文件的大小小于1024字节,则很可能会出现问题。
更正_deepMD5
功能:
function _deepMD5(dir, md5){
var files = fs.readdirSync(dir);
console.info("running with files: ", files)
for(var i = 0; i < files.length; i++){
var fp = dir+path.sep+files[i];
if(fs.lstatSync(fp).isDirectory()){
_deepMD5(fp, md5);
}
else{
var fh = fs.openSync(fp, 'r');
var chunkSize=1024;
var buffer=new Buffer(chunkSize, 'binary');
buffer.fill(0) // that will fix the issue.
while(fs.readSync(fh, buffer, 0, chunkSize, null) != 0){
md5.update(buffer);
}
}
}
}
我希望这会有所帮助。