NodeJS - Синхронное чтение буфера построчно => toString () не удалось - PullRequest
0 голосов
/ 03 мая 2018

Я боролся и долго искал. Я знаю, что есть ответы на этот счет, но ни один не работает.

Для этого я использовал fs.createReadStream и readLine. Но он использует fs.close (), чтобы закрыть чтение файла. поэтому он не работает вообще при использовании в буфере. Чтение всех файлов продолжается без возможности его прервать ...

Тогда я использовал это:

const stream = require('stream');

let bufferStream = new stream.PassThrough();
bufferStream.end(hexaviaFile.buffer);

bufferStream
    .pipe(require('split')())
    .pipe(es.mapSync(function(line){

        // pause the readstream
        bufferStream.pause();

        // DO WHATEVER WITH YOUR LINE
        console.log('line content = ' + line);

        // resume the readstream, possibly from a callback
        bufferStream.resume();

    }).on('error', function(err){
        console.log('Error while reading file.' + err);
    }).on('end', function(){
        console.log('end event !');

    }).on('close', function(){
        console.log('close event !');

    })
);

// toString() Failed

Я получаю ошибку [toString () Failed] и искал ее, по-видимому, она появляется, когда буфер больше, чем максимальный размер буфера узла.

Итак, я проверил:

var buffer = require('buffer');
console.log('buffer.kMaxLength = ',  buffer.kMaxLength); // 2147483647
console.log('hexaviaFile.buffer.byteLength = ',  hexaviaFile.buffer.byteLength); // => 413567671

Это не тот случай, так как вы видите цифры:
* maxBuffer size = 2Go
* мой буфер = 0,4Go

Я также попытался сделать это с помощью другой библиотеки, но:
1. Я хочу, чтобы использование памяти было как можно ниже
2. Мне нужно, чтобы это чтение было идеально синхронизировано. Другими словами, у меня есть некоторые обработки после чтения файла, и мне нужно завершить все чтение, прежде чем перейти к следующим шагам.

Я не знаю, что делать :) Любая помощь приветствуется

Привет.

1 Ответ

0 голосов
/ 11 июня 2018

Я забыл об этом посте. Я нашел способ добиться этого без ошибок.

Это дано здесь: https://github.com/request/request/issues/2826

1-й создает сплиттер для чтения кусочков строк

class Splitter extends Transform {
    constructor(options){
        super(options);
        this.splitSize = options.splitSize;
        this.buffer = Buffer.alloc(0);
        this.continueThis = true;
    }
    stopIt() {
        this.continueThis = false;
    }

    _transform(chunk, encoding, cb){

        this.buffer = Buffer.concat([this.buffer, chunk]);

        while ((this.buffer.length > this.splitSize || this.buffer.length === 1) && this.continueThis){
            try {
                let chunk = this.buffer.slice(0, this.splitSize);

                this.push(chunk);
                this.buffer = this.buffer.slice(this.splitSize);
                if (this.buffer[0] === 26){
                    console.log('EOF : ' + this.buffer[0]);
                }
            } catch (err) {
                console.log('ERR OCCURED => ', err);
                break;
            }
        }
        console.log('WHILE FINISHED');
        cb();
    }
}

Затем перенаправьте его в ваш поток:

let bufferStream = new stream.PassThrough();
bufferStream.end(hugeBuffer);
let splitter = new Splitter({splitSize : 170}); // In my case I have 170 length lines, so I want to process them line by line
let lineNr = 0;
bufferStream
      .pipe(splitter)
      .on('data', async function(line){

          line = line.toString().trim();

          splitter.pause(); // pause stream so you can perform long time processing with await
          lineNr++;

         if (lineNr === 1){
              // DO stuff with 1st line

         } else {
              splitter.stopIt(); // Break the stream and stop reading so we just read 1st line
         }

         splitter.resume() // resumestream so you can process next chunk
    }).on('error', function(err){
            console.log('Error while reading file.' + err);
            // whatever
     }).on('end', async function(){
           console.log('end event');

           // Stream has ended, do whatever...

    });
...