我正在使用Node.js流逐行浏览文本文件,进行一些转换并输出到SVG文件.
我在处理完成后尝试写最后一段数据(< / svg>),但是当写入流发出finish事件时,尝试write()将抛出Error:write after end.
有一种优雅的方式可以解决这个问题吗?
注意:输入文件很大(大约1GB),因此由于其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);
解决方案
解决方案1(通用)
pipe()使用end:false选项写入流并手动end()流.
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,next) { this.push(line); next(); })) .pipe(write_stream,{ end: false }); read_stream.on('end',function() { write_stream.end('</svg>'); });
解决方案2(特定于through / through2转换流)
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,next) { this.push(line); next(); },function(flush) { this.push('</svg>'); flush(); })) .pipe(write_stream);
解决方法
看起来管道在完成时会关闭流.
http://nodejs.org/api/stream.html的文档说明:
By default end() is called on the destination when the source stream emits end,so that destination is no longer writable. Pass { end: false } as options to keep the destination stream open.
This keeps writer open so that “Goodbye” can be written at the end.
reader.pipe(writer,{ end: false }); reader.on('end',function() { writer.end('Goodbye\n'); });