转换流,访问内部数据

时间:2016-03-20 22:35:32

标签: node.js node.js-stream

我想读取一个文件(理想情况下是fs.createReadStream),通过转换过程将其传输,然后将其写入(理想情况下使用fs.createWriteStream)到另一个文件。

我正在使用转换流(new stream.Transform()),它似乎有效,除非现在我被卡住了

在变换流的flush方法中我有

 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 个答案:

答案 0 :(得分: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();
};