createReadStream несколько раз на одном и том же fd


В предыдущем вопросе казалось, что единственный способ сделать чтение произвольного доступа из файла в узле.js использовать fs.createReadStream() с его дополнительным fd, start, и 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, но это оказалось сложно под node. Это также Тест на то, могу ли я запустить с помощью узла.js как язык сценариев общего назначения .

1 2

1 ответ:

Проблема в том, что внешний ReadStream закроет fd после его использования, поэтому повторное использование его на втором ReadStream не удастся. Самый новый узел unstable фактически имеет опции autoClose для ReadStreams, но это еще не часть 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                                
      });                                                                       
    });                                                                         
  }                                                                             
});