我正在学习node.js,并希望编写一个简单的测试程序,将文件从源文件夹复制到目标文件夹。我将fs.ReadStream传送到fs.WriteStream,并且完美无缺。我接下来尝试使用非流动模式,但是下面的程序在较大的文件(超过1MB)上99%的时间都会失败。我假设在给定特定时间的情况下事件队列变空并因此退出。以下程序应该有效吗?
var sourcePath = "./source/test.txt";
var destinationPath = "./destination/test.txt";
// Display number of times 'readable' callback fired
var callbackCount = 0;
process.on('exit', function() {
console.log('Readable callback fired %d times', callbackCount);
})
var fs = require('fs');
var sourceStream = fs.createReadStream(sourcePath);
var destinationStream = fs.createWriteStream(destinationPath);
copyStream(sourceStream, destinationStream);
function copyStream(src, dst) {
var drained = true;
// read chunk of data when ready
src.on('readable', function () {
++callbackCount;
if (!drained) {
dst.once('drain', function () {
writeToDestination();
});
} else {
writeToDestination();
}
function writeToDestination() {
var chunk = src.read();
if (chunk !== null) {
drained = dst.write(chunk);
}
}
});
src.on('end', function () {
dst.end();
});
}
注意:如果我删除了与排水相关的代码,程序总是有效,但node.js文档表明如果write函数返回false,你应该等待排水事件。
上述程序应该按原样运行吗?如果不应该如何重新组织它以同时处理readable
和drain
事件?
答案 0 :(得分:0)
看起来你大部分都在那里;你需要改变一些事情。
dst
时,您需要继续阅读src
,直至获得null
chunk
或dst.write()
返回false
readable
上的所有src
事件,只有在可以写入dst
并且您目前无需编写任何内容时,您应该只监听这些事件。这样的事情:
function copyStream(src, dst) {
function writeToDestination() {
var chunk = src.read(),
drained = true;
// write until dst is saturated or there's no more data available in src
while (drained && (chunk !== null)) {
if (drained = dst.write(chunk)) {
chunk = src.read();
}
}
if (!drained) {
// if dst is saturated, wait for it to drain and then write again
dst.once('drain', function() {
writeToDestination();
});
} else {
// if we ran out of data in src, wait for more and then write again
src.once('readable', function() {
++callbackCount;
writeToDestination();
});
}
}
// trigger the initial write when data is available in src
src.once('readable', function() {
++callbackCount;
writeToDestination();
});
src.on('end', function () {
dst.end();
});
}