How to append to a file in Node?
Solution 1
For occasional appends, you can use appendFile
, which creates a new file handle each time it's called:
const fs = require('fs');
fs.appendFile('message.txt', 'data to append', function (err) {
if (err) throw err;
console.log('Saved!');
});
const fs = require('fs');
fs.appendFileSync('message.txt', 'data to append');
But if you append repeatedly to the same file, it's much better to reuse the file handle.
Solution 2
When you want to write in a log file, i.e. appending data to the end of a file, never use appendFile
. appendFile
opens a file handle for each piece of data you add to your file, after a while you get a beautiful EMFILE
error.
I can add that appendFile
is not easier to use than a WriteStream
.
Example with appendFile
:
console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
fs.appendFile("append.txt", index+ "\n", function (err) {
if (err) console.log(err);
});
});
console.log(new Date().toISOString());
Up to 8000 on my computer, you can append data to the file, then you obtain this:
{ Error: EMFILE: too many open files, open 'C:\mypath\append.txt'
at Error (native)
errno: -4066,
code: 'EMFILE',
syscall: 'open',
path: 'C:\\mypath\\append.txt' }
Moreover, appendFile
will write when it is enabled, so your logs will not be written by timestamp. You can test with example, set 1000 in place of 100000, order will be random, depends on access to file.
If you want to append to a file, you must use a writable stream like this:
var stream = fs.createWriteStream("append.txt", {flags:'a'});
console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
stream.write(index + "\n");
});
console.log(new Date().toISOString());
stream.end();
You end it when you want. You are not even required to use stream.end()
, default option is AutoClose:true
, so your file will end when your process ends and you avoid opening too many files.
Solution 3
Your code using createWriteStream creates a file descriptor for every write. log.end is better because it asks node to close immediately after the write.
var fs = require('fs');
var logStream = fs.createWriteStream('log.txt', {flags: 'a'});
// use {flags: 'a'} to append and {flags: 'w'} to erase and write a new file
logStream.write('Initial line...');
logStream.end('this is the end line');
Solution 4
Besides appendFile
, you can also pass a flag in writeFile
to append data to an existing file.
fs.writeFile('log.txt', 'Hello Node', {'flag':'a'}, function(err) {
if (err) {
return console.error(err);
}
});
By passing flag 'a', data will be appended at the end of the file.
Solution 5
You need to open it, then write to it.
var fs = require('fs'), str = 'string to append to file';
fs.open('filepath', 'a', 666, function( e, id ) {
fs.write( id, 'string to append to file', null, 'utf8', function(){
fs.close(id, function(){
console.log('file closed');
});
});
});
Here's a few links that will help explain the parameters
EDIT: This answer is no longer valid, look into the new fs.appendFile method for appending.
Comments
-
supercobra almost 2 years
I am trying to append a string to a log file. However writeFile will erase the content each time before writing the string.
fs.writeFile('log.txt', 'Hello Node', function (err) { if (err) throw err; console.log('It\'s saved!'); }); // => message.txt erased, contains only 'Hello Node'
Any idea how to do this the easy way?
-
angry kiwi about 13 yearslook like supercobra constantly writes log to the log file, usage of fs.write is not recommended in this case, use fs.createWriteStream instead. Read nodejs.org/docs/v0.4.8/api/all.html#fs.write
-
Ruben Tan almost 13 yearsThe answer is no longer accurate as of nodejs v0.4.10.
-
Zane Claes over 11 yearsanything sync() is almost always a bad idea unless you're 100% sure you absolutely NEED it. Even then, you're probably doing it wrong.
-
nelsonic over 11 yearsDoes anyone know if fs.appendFile keeps a link to the file open so appends are faster? (rather than open/close each write) nodejs.org/api/…
-
Ya Zhuang over 11 yearsit should be '0666' rather than 666.
-
Luis R. over 11 yearsDoesn't mean it's wrong. It just does it Synchronously. Might not be best practice for Node.js, but it's supported.
-
Zane Claes over 11 yearsI was using "ur doin it wrong" in the colloquial internet-meme sense of the phrase. Obviously it's supported =P
-
Patrick Roberts almost 11 years@LuisR. The whole point in using node is to do things asynchronously, allowing the processes to happen in the background while freeing the internal event loop to handle other requests (if it's a server) or other tasks.
-
bryanmac over 10 yearsAgreed on async, but sometimes if you're just writing an interactive script, sync is fine.
-
Jan Święcki about 10 yearsWriting synchronously is absolutely ok if you are doing single user command line app (e.g. script to do some stuff). That way it is faster to do stuff. Why would node have sync methods if not for this purpose?
-
Maël Nison almost 10 years@nelsonic According to the source code, there is no particular treatment.
-
SilentSteel almost 10 yearsIn case it's handy: Note that this is async. This can result in weird timing and other things. Ex: if you have
process.exit()
just afterfs.appendFile
, you may exit before the output is sent. (Usingreturn
is fine.) -
gumenimeda over 9 years@SilentSteel I am seeing some wired behavior where not everything is getting appended to the file. This is at high volume where I am trying to append every 1ms. Do you know what I should be using instead?
-
SilentSteel over 9 yearsWorse case, you can use the synchronous version,
appendFileSync
. nodejs.org/api/… But you may lose one of the great benefits of Node, which is async operations. Make sure you catch errors. Perhaps on some OSes, you can get access denied if requesting the file handle at the same time. Not sure about that. -
Ben over 9 yearsAlso, this creates a file if it doesn't exist. Docs say:
Asynchronously append data to a file, creating the file if it not yet exists. data can be a string or a buffer.
(nodejs.org/api/…) -
Stormbytes about 9 yearsmissing first line! should be 'var fs = require('fs');'
-
Marko Bonaci about 9 yearsOr perhaps even better
var fs = require('graceful-fs')
, which hashed out some known problems. See the docs for more info. -
Gank almost 9 yearsfdW = fsW.openSync("", './log.txt'), 'a') ^ SyntaxError: Unexpected token )
-
fadedbee over 8 yearsDo not use
fs.appendFile
. It is a broken API which uses a new file descriptor for each call. On a busy server (hundreds ofappendFile
per second) this can result in all 1024 file descriptors being used up and the process not being able to open other files. -
zipzit over 8 years@chrisdew Thanks for the update.. but... if we are not to use the accepted answer here, what are we supposed to do? How did you solve this dilema?
-
binki over 7 yearsBoth the initial and end line are on the same line though :-p
-
questionasker over 7 yearshi How to add each data with new line ?
-
laurent about 7 yearsNote that it won't automatically append a newline character, so if it's for something like a log file, a "\n" needs to be manually added at the end.
-
Anish Nair almost 7 yearsPlease note: If you are using
fs.createWriteStream
, then useflags
. If you are usingfs.writeFile
then it'sflag
. Please refer Node JS Docs - File System for more information. -
Anish Nair almost 7 yearsPlease note: If you are using
fs.createWriteStream
, then useflags
. If you are usingfs.writeFile
then it'sflag
. Please refer Node JS Docs - File System for more information. -
Marcus over 6 years@zipzit you asked chrisdew (which I assume is now fadedbee) for an alternative to fs.appendFile. How about the answer from Plaute? It says fs.createWriteStream("append.txt", {flags:'a'}).write(myText);
-
Benny Neugebauer over 6 yearsBe careful! The parameter is not "flags" but "flag" (singular): nodejs.org/api/…
-
Aashish Kumar about 6 yearsThanks for the great answer, but my doubt is that due to asynchronous nature of Javascript, it will execute
stream.end()
before thestream.write()
, so we shouldn't usestream.end()
, also as you mentioned thatAutoClose:True
is a default option then why bother writing a line which is of no use. -
Sharcoux over 5 years
due to asynchronous nature of Javascript
... What? Array.forEach is a synchronous operation. JS is synchronous. It just happens to provide some ways to manage asynchronous operations, like Promises and async/await. -
Qwiso about 5 years@BennyNeugebauer the use of flags is correct, you are not. It was already posted many months before you You've linked docs to fs.writeFile which does use 'flag'. But this solution uses fs.createWriteStream and the parameter 'flags' is correct - nodejs.org/api/fs.html#fs_fs_createwritestream_path_options
-
apple apple about 5 yearsI'd guess
fs.appendFile
result in too many open files because you execute it in asynchronous manner (you're just asynchronously creating 10000 file handle), I believeappendFileSync
would not have similar problem, also notfs.appendFile
with proper interval (1s is probably more than enough) or queueing. -
Radvylf Programs over 4 years@appleapple But you're still opening the file each time. For a log, it makes much more sense to keep it open.
-
apple apple over 4 years@RedwolfPrograms For busy server log, maybe true. For one-time per execution log, maybe not. Anyway, I just state that the point (at least the reason) in this answer is not correct.
-
Dan over 4 yearsFor logs I would just use
fs.appendFileSync
(it can run a million times without issues). If the script crashes or exits right after you log something withstream.write
orfs.appendFile
, it is likely that you won't get the log written (which most likely will be needed to debug the crash/exit) -
noderman about 4 years@fadedbee and @zipzit - old comment, but invaluable. I had a large loop with appends and noticed the thing would get exponentially slower. Best way is to
createWriteStream
withflags : 'a'
and use subsequent<stream>.write
for appending. I believe you can useawait <stream>.write
to make sure the appends are sequential. -
Petr Bugyík over 2 yearsWhat is the reason why you deleted your linked project apickfs from GitHub?
-
Uche Ozoemena over 2 yearsIsn't this by far the easiest of all the answers?