【问题标题】:Fast folder hashing in Windows NodeWindows 节点中的快速文件夹散列
【发布时间】:2015-09-04 18:36:06
【问题描述】:

我正在构建一个 nodewebkit 应用程序,它使本地目录与远程 FTP 保持同步。为了在应用程序第一次运行时构建初始索引,我从远程服务器下载了一个索引文件,其中包含所有文件及其文件夹的哈希值。然后我遍历这个列表并在用户的本地文件夹中找到匹配项。

远程/本地文件夹的总大小可以超过 10GB。可以想象,扫描 10GB 的单个文件可能会非常慢,尤其是在普通 HDD(而非 SSD)上。

节点中是否有一种方法可以有效地获取文件夹的哈希值,而无需遍历和散列其中的每个单独文件?这样,如果文件夹哈希不同,我可以选择是否进行昂贵的单个文件检查(一旦我有一个本地索引可以与远程索引进行比较,我就是这样做的)。

【问题讨论】:

  • 您可能会查看 WIN32 API Win32::DirSize,它应该比原生 File::Find 快 50 倍,例如。

标签: node.js hash node-webkit


【解决方案1】:

您可以迭代地遍历目录,统计目录及其包含的每个文件,而不是跟踪链接并生成哈希。这是一个例子:

'use strict';

// npm install siphash
var siphash = require('siphash');
// npm install walk
var walk = require('walk');

var key = siphash.string16_to_key('0123456789ABCDEF');
var walker  = walk.walk('/tmp', {followLinks: false});

walker.on('directories', directoryHandler);
walker.on('file', fileHandler);
walker.on('errors', errorsHandler); // plural
walker.on('end', endHandler);

var directories = {};
var directoryHashes = [];

function addRootDirectory(name, stats) {
    directories[name] = directories[name] || {
        fileStats: []
    };

    if(stats.file) directories[name].fileStats.push(stats.file);
    else if(stats.dir) directories[name].dirStats = stats.dir;
}

function directoryHandler(root, dirStatsArray, next) {
    addRootDirectory(root, {dir:dirStatsArray});
    next();
}

function fileHandler(root, fileStat, next) {
    addRootDirectory(root, {file:fileStat});
    next();
}

function errorsHandler(root, nodeStatsArray, next) {
    nodeStatsArray.forEach(function (n) {
        console.error('[ERROR] ' + n.name);
        console.error(n.error.message || (n.error.code + ': ' + n.error.path));
    });
    next();
}

function endHandler() {
    Object.keys(directories).forEach(function (dir) {
        var hash = siphash.hash_hex(key, JSON.stringify(dir));
        directoryHashes.push({
            dir: dir,
            hash: hash
        });
    });

    console.log(directoryHashes);
}

您当然希望将其转换为某种命令行应用程序,以便可能接受参数并仔细检查文件是否每次都以正确的顺序返回(可能在散列之前根据文件名对文件统计信息进行排序!) 以便 siphash 每次都返回正确的哈希值。

这不是经过测试的代码.. 只是为了提供一个我可能会从这类事情开始的示例。

编辑:为了减少依赖关系,如果你想要require('crypto');,你可以使用 Node 的加密库而不是 siphash,当然如果你愿意,你可以自己遍历/统计目录和文件。

【讨论】:

  • 谢谢,我实际上已经在使用加密来获取哈希了!这种方法实际上并没有检查内容吗?因此,如果文件中的某个字符与远程目录不同,此方法不会检测到这一点?
  • 是的,它不会检查内容,但会统计应该包含修改后时间戳的文件,所以这将是一个快速检查,您可能可以更频繁地进行检查。散列文件内容可能是显着减慢速度的原因,这就是为什么我在想,如果我这样做,我可能会从这样的快速检查开始,然后可能不那么定期地进行更全面的检查。
  • 实际上,我可能希望在这些文件的持久存储中维护远程和本地最后一个哈希结果,以便如果文件在客户端或服务器上更新,它可以比较最后一个哈希在具有当前存储的持久存储中 - 可能是 redis 的一个很好的用例。我不会直接比较服务器和客户端上的统计信息,因为这些文件统计信息 - 节点和诸如此类的东西之间当然会有所不同。
  • 但是,与独立持久存储中的最后一个已知哈希进行比较也可以提供一些速度优势,并且不需要在客户端和服务器之间建立频繁的连接。服务器可以独立检查其目录和文件内容,而客户端执行相同的操作,如果检测到其中任何一个有差异,则可以在该文件的持久存储上设置一个标志,以便客户端可以与该文件建立更昂贵的连接。服务器获取最新文件(反之亦然)。
  • 比较两个哈希索引正是我在完成第一次完整扫描后所做的,它自然非常快。这只是在我拥有本地哈希索引之前我需要加速的第一次完整扫描。不幸的是,时间戳并没有多大用处,因为客户端可以在服务器之前很久就添加文件。
猜你喜欢
  • 1970-01-01
  • 2016-07-25
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
相关资源
最近更新 更多