Hesham Yassin Hesham Yassin - 29 days ago 14
Node.js Question

Nodejs Stream doesn't update file after end

I am trying to merge small files to one file using streaming.
After i write the data and call

streamWrite.end()
, the file size still 0. when the program finishes to run, the file is filled with the data that i wrote.

My Question is:
why the file size was 0 after i called writeStream.end() and how to solve this?

Here is the whole code

var fs = require('fs');

function createRandomJsonFiles(destPath,numOfFiles,minFileSize)
{
for(var i=0;i<numOfFiles;i++){
var tmp = {};
tmp.k1 = new Array(Math.floor(Math.random() * minFileSize) + minFileSize ).join( 'a' );
fs.writeFileSync(destPath+'/testfile.'+i, JSON.stringify(tmp));
}
}

createRandomJsonFiles("./testFiles/",1000,100); // create some files

var streamWrite = fs.createWriteStream('write.tst');

var files = fs.readdirSync("./testFiles/");
for (var i = 0; i < files.length; ++i) { // merge the files to one file
var inputPath = "./testFiles/" + files[i];
var file_data = fs.readFileSync(inputPath).toString();
var canContinue = streamWrite.write(file_data); // write the chunk to the file system and close the stream
if (!canContinue){
streamWrite.emit('drain');
}
}
streamWrite.end();
var chunkContent = fs.readFileSync('write.tst').toString();
console.log(chunkContent);

Answer

The problem is that end() is asynchronous. Consider the following code that I used to test this.

var fs = require("fs");

var stream1 = fs.createWriteStream("a");
stream1.write("hello");
stream1.end();
console.log(fs.readFileSync("a").toString());

var stream2 = fs.createWriteStream("b");
stream2.write("hello");
stream2.end(function() {
    console.log(fs.readFileSync("b").toString());
});

This will print nothing the first time, but hello the second time. You should change the last 3 lines of your code to

streamWrite.end(function() {
    var chunkContent = fs.readFileSync('write.tst').toString();
    console.log(chunkContent);
});