我正在通过尝试重新创建一些我在C#中编写过的实用程序应用程序来匆忙学习Node.js。我对我正在写的一个程序中发生的事情感到困惑。我想要这个程序要做的是在文件系统上打开一个文件,gzip该文件,然后将gzip压缩数据发送到另一台服务器。为了测试,我决定“将gzip压缩数据保存到文件系统,然后再读回来验证你做对了。”
所以我希望我的程序能做的是:
反而会发生什么:
这是我的代码(如果我的风格很糟糕,请不要向我扔石头!):
var inputFilePath = "data.xml";
var fs = require('fs');
var zlib = require('zlib');
var inputStream = fs.createReadStream(inputFilePath)
.on('end', function() {
console.log("Created test output file.");
});
var gzipStream = zlib.createGzip();
inputStream.pipe(gzipStream);
var outputFile = fs.createWriteStream('output.gzip');
gzipStream.pipe(outputFile);
console.log('Attempting to re-read the data.');
var testInput = fs.createReadStream('output.gzip');
var unzip = zlib.createGunzip();
testInput.pipe(unzip).on('data', function(chunk) {
console.log(chunk.toString('utf8'));
});
我怀疑流媒体内容是异步发生的,这就是为什么我看到控制台输出的顺序与我预期的不同。如果这是真的,这是一个问题,因为我在尝试打开之前需要输出文件准备就绪。我注意到writable.end()
并且认为这将是解决方案,但我不明白当我在不同的地方调用它时会发生什么:
outputFile.end()
,则输出文件为空。我想这是因为它在写入发生之前关闭了流。gzipStream.end()
,我不会收到“创建的测试输出文件”消息,但会创建一个消息!修改
我想出了第二部分。在给定的代码中,我应该在data
流之前设置unzip
事件的处理程序,然后再调用pipe()
。现在设置代码的方式,我设置为在管道返回的流上处理事件,但从不从THAT流中读取,因此我的处理程序永远不会被调用。
答案 0 :(得分:0)
我偶然发现了这个解决方案。从概念上看,表达我想要一个订单的方式就是说,“当输入流中没有更多数据时,开始处理它生成的输出文件。”大大简化:
var inputFilePath = "data.xml";
var fs = require('fs');
var zlib = require('zlib');
function testOutput() {
console.log('Attempting to re-read the data.');
var testInput = fs.createReadStream('output.gzip');
var unzip = zlib.createGunzip();
unzip.on('data', function(chunk) {
console.log(chunk.toString('utf8'))
});
testInput.pipe(unzip);
};
// Load input file stream
var inputStream = fs.createReadStream(inputFilePath);
// Pipe the file stream into a gzip stream
var gzipStream = zlib.createGzip();
gzipStream.on('end', function() {
console.log("Created test output file.");
testOutput();
});
var outputFile = fs.createWriteStream('output.gzip');
inputStream.pipe(gzipStream).pipe(outputFile);
pipe()
调用清空inputStream
,然后gzipStream
,调用testOutput()
。