Трансформировать поток, получая доступ к внутренним данным

Я хочу прочитать файл (в идеале с fs.createReadStream, передать его через процесс преобразования, а затем записать его (в идеале, используя fs.createWriteStream) в другой файл.

Я использую поток преобразования (new stream.Transform()) для этого и вроде бы работает, разве что теперь я застрял

в методе потока потока преобразования у меня есть

 strm._flush = function (done) {
        if (this._lastLineData) {
            this.push(this._lastLineData + '\n');
        }
        this._lastLineData = null;
        done();
    };

Я хочу иметь возможность изменять некоторые данные во внутренней структуре данных, где преобразование хранит данные. Как я могу получить доступ к этой внутренней структуре данных.

Другими словами, this.push, безусловно, выдвигает на некоторый массив, я хочу иметь возможность читать из определенных элементов этого массива в методе _flush.

Заходя в ядро ​​узла, я вижу это:

Transform.prototype.push = function(chunk, encoding) {
  this._transformState.needTransform = false;
  return Duplex.prototype.push.call(this, chunk, encoding);
};

а также

Readable.prototype.push = function(chunk, encoding) {
  var state = this._readableState;

  if (!state.objectMode && typeof chunk === 'string') {
    encoding = encoding || state.defaultEncoding;
    if (encoding !== state.encoding) {
      chunk = new Buffer(chunk, encoding);
      encoding = '';
    }
  }

  return readableAddChunk(this, state, chunk, encoding, false);
};

а также

function readableAddChunk(stream, state, chunk, encoding, addToFront) {
  var er = chunkInvalid(state, chunk);
  if (er) {
    stream.emit('error', er);
  } else if (chunk === null) {
    state.reading = false;
    onEofChunk(stream, state);
  } else if (state.objectMode || chunk && chunk.length > 0) {
    if (state.ended && !addToFront) {
      var e = new Error('stream.push() after EOF');
      stream.emit('error', e);
    } else if (state.endEmitted && addToFront) {
      var e = new Error('stream.unshift() after end event');
      stream.emit('error', e);
    } else {
      if (state.decoder && !addToFront && !encoding)
        chunk = state.decoder.write(chunk);

      if (!addToFront)
        state.reading = false;

      // if we want the data now, just emit it.
      if (state.flowing && state.length === 0 && !state.sync) {
        stream.emit('data', chunk);
        stream.read(0);
      } else {
        // update the buffer info.
        state.length += state.objectMode ? 1 : chunk.length;
        if (addToFront)
          state.buffer.unshift(chunk);
        else
          state.buffer.push(chunk);

        if (state.needReadable)
          emitReadable(stream);
      }

      maybeReadMore(stream, state);
    }
  } else if (!addToFront) {
    state.reading = false;
  }

  return needMoreData(state);
}

так что мне кажется нет простого способа добраться до внутренних данных?

1 ответ

Вы не можете сделать это.

Для чего нужно использовать потоки - это передавать данные из одного места в другое. Если вы хотите изменить данные целиком (перед тем, как передать их в следующий поток), вам не следует использовать поток вообще. Думайте о них как о бесконечном потоке данных.

Что вы можете сделать, это:

var data = [];

stream._transform = function(chunk, enc, done) { 
   data.push(chunk);
   done(chunk);
}

stream._flush = function(done) { 
   /** ... Do something with data ... */
   data = []; // Null data variable, to allow GC collecting it.
   done();
};
Другие вопросы по тегам