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上的文档声明:
默认情况下,在源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'
。 我还没有使用它。