wyc
wyc

Reputation: 55273

Why is the following fs.writeFile only writing data from the last file?

I want to read the content of two files (same folder) and write them into a single one:

  const input = process.argv[2]

  fs.readdir(__dirname + `/${input}/`, (err, files) => {
    if (err) {
      return
    }

    files.forEach((file) => {
      fs.readFile(__dirname + `/${input}/` + file, 'utf8', (err, data) => {
        let items = []
        items.unshift(data)
        let result = items.join('\n\n')

        fs.writeFile("untitled2.html", result, (err) => {
          if (err) {
            console.log(err)
          } else {
            console.log(result)
          }
        })
      })
    })
  })

console.log(result) outputs the content of the two files:

alex@alex-K43U:~/node/m2n/bin$ node index4.js folder

File 1

File 2

The file, however, has only the content from the second file:

File 2

What's happening here?

Upvotes: 2

Views: 1841

Answers (2)

Denys Séguret
Denys Séguret

Reputation: 382150

Don't use writeFile but appendFile when your goal is to append to a file without replacing the content (appendFile takes care of creating the file when necessary).

You're also not waiting for the appending to be finished, which might lead to errors. You have various solutions here:

  • promises
  • a recursive function handling files one after the other
  • use appendFileSync (assuming you're writing an utility rather than a server)

Exemple with the recursive function:

(function doOneFile(){
    var file = files.shift();
    if (!file) return;
    fs.readFile(__dirname + `/${input}/` + file, 'utf8', (err, data) => {
        let items = []
        items.unshift(data)
        let result = items.join('\n\n')

        fs.appendFile("untitled2.html", result, (err) => {
          if (err) {
            console.log(err)
          } else {
            console.log(result)
          }
          doOneFile();
        })
    })
})();

Upvotes: 3

Mathias Dolidon
Mathias Dolidon

Reputation: 3903

With the default options, writeFile erases previous contents every time. It's the "write mode". What you want is switch to "append mode", like so :

fs.writeFile("untitled2.html", result, {flag:"a"}, callbacks...);

In the process, you'll need to take care to erase the possible file contents before your loop, or have the first access be in write mode. Otherwise you'll keep appending to previsously existing contents.

Besides, in this case you'll be hitting problems with concurrent accesses. Either use the synchronous forms, or loop through files via a callback.

Upvotes: 1

Related Questions