Nam Nguyen
Nam Nguyen

Reputation: 5750

Node.js concatinating files

I'm trying to concatenate multiple files and save to a new file using node js createWriteStream and createReadStream. I have a small bug that I would like to print out the file name before its contents. However, the file name is always printed on top of the output file. Please see my result output and if you have any ideas why, please help!

Thanks!

test.js

var async = require('async');
var fs = require('fs');
var path = require('path');

var SOURCE_FOLDER = '/tmp/test';
var SOURCE_FILE_PATTERN = /\.json$/
var REPORT_FILE = path.join(SOURCE_FOLDER, 'output.html');

var writeStream = fs.createWriteStream(REPORT_FILE, {
  flags: 'w',
  encoding: 'UTF-8'
});

var appendReport = function appendReport(file, callback) {
  var readStream = fs.createReadStream(file, {
    flags: 'r',
    encoding: 'UTF-8'
  });

  readStream.pipe(writeStream, {
    end: false
  });

  readStream.on('end', callback);
};

fs.readdir(SOURCE_FOLDER, function (err, files) {
  if (err) {
    console.log(err);
  } else {
    writeStream.write("<html><body><pre>\n");

    async.forEach(files, function (file, callback) {
      var filePath = path.join(SOURCE_FOLDER, file);

      fs.stat(filePath, function (err, stats) {
        if (err) {
          callback(err);
        } else if (stats.isFile() && file.match(SOURCE_FILE_PATTERN)) {
          writeStream.write("\n" + filePath);
          appendReport(filePath, callback);
        } else {
          callback();
        }
      });
    }, function (err) {
      writeStream.write("\n</pre></body></html>");
    });
  }
});

My Current Result:

# node test.js; cat /tmp/test/output.html 
<html><body><pre>

/tmp/test/a.json
/tmp/test/b.jsoncontent A
content B

</pre></body></html>

My Expected Result:

# node test.js; cat /tmp/test/output.html 
<html><body><pre>

/tmp/test/a.json
content A

/tmp/test/b.json
content B

</pre></body></html>

Upvotes: 1

Views: 110

Answers (1)

mscdex
mscdex

Reputation: 106698

The problem is that async.forEach === async.each and async.each() calls the iterator in parallel. What you want is async.eachSeries() instead.

Upvotes: 1

Related Questions