从Node.jsencryption库获得奇怪的结果

我试图编写一个函数来recursion获取目录中所有文件的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(".")); 

当你创build一个新的缓冲区时,它不会被清除。 所以你从一个随机填充的缓冲区开始 – 这是运行之间的变化来自哪里。

接下来,您读取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)); } 

为了效率的缘故,当我们不需要的时候,我避免了切片。 当然,如果您更喜欢较短的代码,并且不担心性能,那么您可以每次分片。

在你的代码中需要做一个非常小的改变,使其按预期工作:你需要使用buffer.fill(0)重新创build你的新缓冲区。

new Buffer()expression式分配内存,但不清除它,所以你必须手动完成。 如果你所有的文件都超过1024字节的大小,你可能不会注意到这个问题。 但是,如果至less有一个文件的大小小于1024字节,这个问题很可能会发生。

更正_deepMD5function:

 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); } } } } 

我希望这会有所帮助。