在同一个fd上多次createReadStream

时间:2012-12-24 00:12:15

标签: node.js random-access

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

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

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扩展实现了这个项目,但它在节点下证明是困难的。这也是我是否可以开始using node.js as a general purpose scripting language的测试。

1 个答案:

答案 0 :(得分:3)

问题是外部ReadStream会在使用后关闭fd,因此在第二个ReadStream上重复使用它会失败。最新的Node unstable实际上为autoClose提供了ReadStreams选项,但这不是稳定的一部分。

真正的答案是,您在上一个问题中提供给您的信息不正确。 createReadStream是使用所有公共API实现的,因此您无法做到这一点,也无法做到。在这种情况下,您可以将fs.readposition参数一起使用。

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