我正在匆忙地学习Node.js,试图重新创建一些我曾经用C#编写过的实用程序。我对我正在写的一个程序中发生的事情有点困惑。我想让这个程序打开文件系统上的一个文件,对该文件进行gzip处理,然后将经过gzip处理的数据发送到另一台服务器。为了进行测试,我决定"将gzipped数据保存到文件系统,然后读回以验证是否正确。">
所以我希望我的程序能做的是:
- 创建输出文件
- 打印"创建的测试输出文件">
- 打印"正在尝试重新读取数据。">
- 读取文件
- 将纯文本输出到控制台
相反会发生什么:
- 将创建输出文件
- 打印"正在尝试重新读取数据。">
- 打印"已创建测试输出文件。">
- 我没有控制台输出
这是我的代码(如果我的风格很糟糕,请不要向我扔石头!):
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()
,我不会得到"Created test output file"消息,但已经创建了一个
编辑
我想好了第二部分。在给定的代码中,我应该在调用pipe()
之前,从unzip
流设置data
事件的处理程序。按照现在设置代码的方式,我设置为处理管道返回的流上的事件,但从不读取该流,因此我的处理程序永远不会被调用。
我偶然发现了这个解决方案。从概念上看,表达我想要订单的方式是说,"当输入流中没有更多数据时,开始处理它生成的输出文件。">
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()
。