【问题标题】:How to check if two files have the same content?如何检查两个文件是否具有相同的内容?
【发布时间】:2014-11-05 03:35:29
【问题描述】:

我正在使用mocha/supertest/should.js 测试 REST 服务

GET /files/<hash> 将文件作为流返回。

如何在should.js 中断言文件内容相同?

it('should return file as stream', function (done) {
    var writeStream = fs.createWriteStream('test/fixtures/tmp.json');
    
    var req = api.get('/files/676dfg1430af3595');
    req.on('end', function(){
       var tmpBuf = fs.readFileSync('test/fixtures/tmp.json');
       var testBuf = fs.readFileSync('test/fixtures/test.json');
    
       // How to assert with should.js file contents are the same (tmpBuf == testBuf )
       // ...
    
       done();
    });
});

【问题讨论】:

    标签: javascript node.js compare mocha.js should.js


    【解决方案1】:

    令人惊讶的是,没有人建议Buffer.equals。从 v0.11 开始,这似乎是最快和最简单的方法。

    所以你的代码会变成tmpBuf.equals(testBuf)

    【讨论】:

    • 最好的解决方案是最简单的
    【解决方案2】:

    您有 3 个解决方案:

    第一

    比较结果字符串

    tmpBuf.toString() === testBuf.toString();
    

    第二

    使用循环逐字节读取缓冲区

    var index = 0,
        length = tmpBuf.length,
        match = true;
    
    while (index < length) {
        if (tmpBuf[index] === testBuf[index]) {
            index++;
        } else {
            match = false;
            break;
        }
    }
    
    match; // true -> contents are the same, false -> otherwise
    

    第三

    使用第三方模块,如 buffertools 和 buffertools.compare(buffer, buffer|string) 方法。

    【讨论】:

      【解决方案3】:

      should.js 中,您可以使用.eql 来比较Buffer 的实例:

      > var buf1 = new Buffer('abc');
      undefined
      > var buf2 = new Buffer('abc');
      undefined
      > var buf3 = new Buffer('dsfg');
      undefined
      > buf1.should.be.eql(buf1)
      ...
      > buf1.should.be.eql(buf2)
      ...
      > buf1.should.be.eql(buf3)
      AssertionError: expected <Buffer 61 62 63> to equal <Buffer 64 73 66 67>
          ...
      > 
      

      【讨论】:

        【解决方案4】:

        使用file-comparenode-temp 的解决方案:

        it('should return test2.json as a stream', function (done) {
            var writeStream = temp.createWriteStream();
            temp.track();
        
            var req = api.get('/files/7386afde8992');
        
            req.on('end', function() {
                comparator.compare(writeStream.path, TEST2_JSON_FILE, function(result, err) {
                    if (err) {
                        return done(err);
                    }
        
                    result.should.true;
                    done();
                });
            });
        
            req.pipe(writeStream);
        });
        

        【讨论】:

          【解决方案5】:

          用于比较大文件,例如断言文件上传时的图像将缓冲区或字符串与should.eql 进行比较需要很长时间。我建议使用 crypto 模块声明缓冲区哈希:

          const buf1Hash = crypto.createHash('sha256').update(buf1).digest();
          const buf2Hash = crypto.createHash('sha256').update(buf2).digest();
          buf1Hash.should.eql(buf2Hash);
          

          一种更简单的方法是断言缓冲区长度,如下所示:

          buf1.length.should.eql(buf2.length)
          

          您当然可以使用不同的工具,而不是使用 shouldjs 作为断言模块

          【讨论】:

          • 请不要使用哈希。由于Pigeon Hole 原则,散列通常是唯一的,但并不总是唯一。此外,生成哈希所需的计算比简单地比较原始内容要昂贵得多。
          • 老兄,sha256 是一个加密安全的哈希函数。拥有 2 个不同文件的哈希值的概率是如此之小,以至于提及它是荒谬的。
          • 加密库必须遍历所有字节来计算哈希。如果您已经将两个缓冲区完全保存在内存中,那么计算它们的哈希值是没有意义的。直接比较它们的内容不仅更容易阅读,而且速度更快(因为可以跳过哈希计算)。仅当文件太大而无法将它们保存在内存中以运行直接比较时,哈希在这里才有用。
          【解决方案6】:

          我认为你应该在 JavaScript 中使用non-blocking calls 以获得更好的性能,至少可以防止阻塞其他操作:

          阻塞是指在 Node.js 进程中执行额外的 JavaScript 必须等到非 JavaScript 操作完成。发生这种情况是因为在发生阻塞操作时事件循环无法继续运行 JavaScript。

          在 Node.js 中,由于 CPU 密集型而不是等待非 JavaScript 操作(例如 I/O)而表现出较差性能的 JavaScript 通常不称为阻塞。 Node.js 标准库中使用 libuv 的同步方法是最常用的阻塞操作。原生模块也可能有阻塞方法。

          因此,我将使用类似于以下代码的内容更改 Sync 调用。另外,我会使用Max 建议的方法equals 来比较两个文件:

          const fs = require('fs')
          
          fs.readFile('file1', (err, data1) => {
              if (err) throw err;
              fs.readFile('file2', (err, data2) => {
                  if (err) throw err;
                  if (data1.equals(data2)) {
                      console.log('EQUAL')
                  } else {
                      console.log('NON EQUAL')
                  }
          
              });
          });
          

          虽然对于一个小而单一的脚本,结果几乎是一样的

          【讨论】:

            猜你喜欢
            • 2012-03-29
            • 1970-01-01
            • 1970-01-01
            • 2014-06-11
            • 2012-06-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-02-10
            相关资源
            最近更新 更多