删除 NodeJs Stream 填充

Remove NodeJs Stream padding

我正在编写一个应用程序,我需要从流中删除前 X 字节和最后 Y 字节。所以我基本上需要的是一个可以传递给 pipe 的函数,它将 X 和 Y 作为参数,并在流通过时从流中删除所需的字节数。我的简化设置是这样的:

const rs = fs.createReadStream('some_file')
const ws = fs.createWriteStream('some_other_file')
rs.pipe(streamPadding(128, 512)).pipe(ws)

之后,some_other_file应该包含some_file减去前128字节和后512字节的所有内容。我已经阅读了流,但无法弄清楚如何正确地执行此操作,以便它也能处理传输过程中的错误并正确执行背压。

据我所知,我需要一个双工流,每当我从它读取时,从它的输入流中读取,跟踪我们在流中的位置并在发出前跳过前 128 个字节数据。关于如何实施的一些提示将非常有帮助。

第二部分似乎更难,如果不是不可能的话,因为在输入流实际关闭之前,我怎么知道我是否已经达到最后 512 个字节。我怀疑这可能不可能,但我相信一定有办法解决这个问题,所以如果您对此有任何建议,我将不胜感激!

您可以创建一个新的 Transform 流来执行您想要的操作。至于丢失最后 x 个字节,您始终可以保留最后 x 个字节的缓冲,并在流结束时忽略它们。

像这样(假设您正在使用缓冲区)。


const {Transform} = require('stream');


const ignoreFirst = 128,
      ignoreLast = 512;

let lastBuff,
    cnt = 0;

const MyTrimmer = new Transform({
  transform(chunk,encoding,callback) {
    let len = Buffer.byteLength(chunk);

    // If we haven't ignored the first bit yet, make sure we do
    if(cnt <= ignoreFirst) {
      let diff = ignoreFirst - cnt;

      // If we have more than we want to ignore, adjust pointer
      if(len > diff)
        chunk = chunk.slice(diff,len);
      // Otherwise unset chunk for later
      else
        chunk = undefined;
    }

    // Keep track of how many bytes we've seen
    cnt += len;

    // If we have nothing to push after trimming, just get out
    if(!chunk)
      return callback();

    // If we already have a saved buff, concat it with the chunk
    if(lastBuff)
      chunk = Buffer.concat([lastBuff,chunk]);
    
    // Get the new chunk length
    len = Buffer.byteLength(chunk);
    
    // If the length is less than what we ignore at the end, save it and get out
    if(len < ignoreLast) {
      lastBuff = chunk;
      return callback();
    }

    // Otherwise save the piece we might want to ignore and push the rest through
    lastBuff = chunk.slice(len-ignoreLast,len);
    this.push(chunk.slice(0,len-ignoreLast));
    callback();
  }
});


然后你添加你的管道,假设你正在从文件读取和写入文件:

const rs = fs.createReadStream('some_file')
const ws = fs.createWriteStream('some_other_file')

myTrimmer.pipe(ws);
rs.pipe(myTrimmer);