【问题标题】:createReadStream multiple times on the same fd在同一个 fd 上多次 createReadStream
【发布时间】:2012-12-24 00:12:15
【问题描述】:

In a previous question 似乎从 node.js 中的文件进行随机访问读取的唯一方法是使用 fs.createReadStream() 及其可选的 fdstartend 字段。

这在我最简单的测试中运行良好。但在我的项目中,我需要反复读取二进制文件的不同偏移量。这以一种奇怪的方式失败了,所以我想出了一个最小的测试用例:

var fs = require('fs');

fs.open('test.txt', 'r', function (err, fd) {
  if (err) {
    console.error('error opening file: ' + err);
  } else {
    fs.createReadStream(null, {fd: fd, start: 2, end: 5}).on('error', function (err) {
        throw e;
      }).on('close', function () {
        console.log('outer close');
      }).on('data', function (data) {
        console.log('outer data', data);
      }).on('end', function () {
        console.log('outer end');

        fs.createReadStream(null, {fd: fd, start: 0, end: 3}).on('error', function (err) {
            throw e;
          }).on('close', function () {
            console.log('inner close');
          }).on('data', function (data) {
            console.log('inner data', data);
          }).on('end', function () {
            console.log('inner end');

            // more code to execute after both reads
          });
      });
  }
});

从未收到内部end 事件。 (外层close接收不一致,但我不需要附加代码。)

我之前在 Perl 中甚至在 JavaScript 中作为 Firefox 扩展实现过这个项目,但在 node.js 下它被证明是困难的。这也是对我是否可以开始using node.js as a general purpose scripting language的测试。

【问题讨论】:

    标签: node.js random-access


    【解决方案1】:

    问题是外部ReadStream在使用后会关闭fd,所以在第二个ReadStream上重复使用会失败。最新的 Node 不稳定实际上有 ReadStreamsautoClose 选项,但这还不是 stable 的一部分。

    真正的答案是您在上一个问题中提供给您的信息不正确。 createReadStream 是使用所有公共 API 实现的,所以没有什么是你不能做的。在这种情况下,您可以只使用 fs.read 及其 position 参数。

    var fs = require('fs');                                                         
    
    fs.open('test.txt', 'r', function (err, fd) {                                   
      if (err) {                                                                    
        console.error('error opening file: ' + err);                                
      } else {                                                                      
        fs.read(fd, new Buffer(4), 0, 4, 2, function(err, bytesRead, data){        
          if (err) throw err;                                                       
          console.log('outer data', data);                                          
    
          fs.read(fd, new Buffer(3), 0, 3, 0, function(err, bytesRead, data2){   
            if (err) throw err;                                                     
            console.log('inner data', data2);                                       
            fs.close(fd);                                                           
    
            // more code to execute after both reads                                
          });                                                                       
        });                                                                         
      }                                                                             
    });   
    

    【讨论】:

    • 谢谢@loganfsmyth!我希望在fs.read() 中有这样的选项,但不知何故,当我阅读它的文档时,我设法将offsetposition 参数混为一谈,只注意到offset 在开始读取的缓冲区内偏移!如果您也为上一个问题提供答案,那就太好了。
    • fs.read 很好地解决了这个问题,但我随后的问题需要随机访问和一次读取一行。使用流更容易实现行读取,但只能使用fs.read 进行查找。我找不到允许将两者与简单代码混合的解决方案。
    • @hippietrail 流如何让查找换行变得更容易?流是用fs.read 实现的,所以你应该能够复制它拥有的任何逻辑。
    • 流不会使查找换行变得更容易,它们使保持多字节序列不中断更容易。你是说我应该用fs.read 为我自己的行阅读代码复制Streams 中的逻辑吗?软件工程师避免重新发明轮子。我看了看,处理 UTF-8 序列等的代码确实不是特别简单。对我来说,这是一个反对 node.js 作为通用脚本语言的标志。我知道这不是 node 的目标,但在许多其他方面它有可能做 Perl/Python/Ruby 一直在做的事情,但更好。
    • @hippietrail 文档不是很清楚,但这就是 StringDecoder 所做的。如果你向它传递一个以部分字符结尾的缓冲区,它将返回之前的所有有效字符,并将部分字符缓冲到传递给write() next 的任何内容之前。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2019-01-06
    • 2014-12-29
    相关资源
    最近更新 更多