Node.js:如何在Write Stream“finish”事件上写入()

我使用Node.jsstream逐行扫描文本文件,进行一些转换并输出到SVG文件。

我试图在处理完成后写入最后一块数据( </svg> ),但是在写入stream发出finish事件的时候,尝试write()将抛出Error: write after end

有没有一种优雅的方式可以解决这个问题?

注意:input文件很大(大约1GB),所以没有经过pipe()方法,因为它的I / O和内存pipe理。

 var fs = require('fs'); var split2 = require('split2'); var through2 = require('through2'); var read_stream = fs.createReadStream('input.txt'); var write_stream = fs.createWriteStream('output.svg'); write_stream.write('<svg>'); write_stream.on('finish', function() { this.write('</svg>'); // doesn't work }); read_stream .pipe(split2()) .pipe(through2.obj(function(line, encoding, next) { this.push(line); next(); })) .pipe(write_stream); 

解决scheme

感谢乔丹 & pNre帮我弄明白这一点。

解决scheme1(通用)

pipe()写入stream的end:false选项并手动end()stream。

 var fs = require('fs'); var split2 = require('split2'); var through2 = require('through2'); var read_stream = fs.createReadStream('input.txt'); var write_stream = fs.createWriteStream('output.svg'); write_stream.write('<svg>'); read_stream .pipe(split2()) .pipe(through2.obj(function(line, encoding, next) { this.push(line); next(); })) .pipe(write_stream, { end: false }); read_stream.on('end', function() { write_stream.end('</svg>'); }); 

解决scheme2(特定于through / through2转换stream)

through2具有可用于写入最终数据的刷新function。

 var fs = require('fs'); var split2 = require('split2'); var through2 = require('through2'); var read_stream = fs.createReadStream('input.txt'); var write_stream = fs.createWriteStream('output.svg'); write_stream.write('<svg>'); read_stream .pipe(split2()) .pipe(through2.obj(function(line, encoding, next) { this.push(line); next(); }, function(flush) { this.push('</svg>'); flush(); })) .pipe(write_stream); 

看起来,pipe道在完成时closures了stream。

http://nodejs.org/api/stream.html上的文档声明&#xFF1A;

默认情况下,在源stream发出结束时,在目标上调用end(),以便目标不再可写。 通过{end:false}作为选项来保持目标stream的打开。

这样可以保持作家的开放性,最终可以写下“再见”。

 reader.pipe(writer, { end: false }); reader.on('end', function() { writer.end('Goodbye\n'); }); 

你有没有考虑创build一个新的stream来追加</svg>标签? through可以帮助你:

 var fs = require('fs'); var split2 = require('split2'); var through = require('through'); var read_stream = fs.createReadStream('input.txt'); var write_stream = fs.createWriteStream('output.svg'); write_stream.write('<svg>'); var tag = through(function write(data) { this.queue(data); }, function end() { this.queue('</svg>'); }); read_stream.pipe(split2()).pipe(some_transform).pipe(tag).pipe(write_stream); 

似乎有一个没有logging的事件被称为'prefinish' 。 我还没有使用它。