Writing to files in Node.js

1,849,015

Solution 1

There are a lot of details in the File System API. The most common way is:

const fs = require('fs');

fs.writeFile("/tmp/test", "Hey there!", function(err) {
    if(err) {
        return console.log(err);
    }
    console.log("The file was saved!");
}); 

// Or
fs.writeFileSync('/tmp/test-sync', 'Hey there!');

Solution 2

Currently there are three ways to write a file:

  1. fs.write(fd, buffer, offset, length, position, callback)

    You need to wait for the callback to ensure that the buffer is written to disk. It's not buffered.

  2. fs.writeFile(filename, data, [encoding], callback)

    All data must be stored at the same time; you cannot perform sequential writes.

  3. fs.createWriteStream(path, [options])

    Creates a WriteStream, which is convenient because you don't need to wait for a callback. But again, it's not buffered.

A WriteStream, as the name says, is a stream. A stream by definition is “a buffer” containing data which moves in one direction (source ► destination). But a writable stream is not necessarily “buffered”. A stream is “buffered” when you write n times, and at time n+1, the stream sends the buffer to the kernel (because it's full and needs to be flushed).

In other words: “A buffer” is the object. Whether or not it “is buffered” is a property of that object.

If you look at the code, the WriteStream inherits from a writable Stream object. If you pay attention, you’ll see how they flush the content; they don't have any buffering system.

If you write a string, it’s converted to a buffer, and then sent to the native layer and written to disk. When writing strings, they're not filling up any buffer. So, if you do:

write("a")
write("b")
write("c")

You're doing:

fs.write(new Buffer("a"))
fs.write(new Buffer("b"))
fs.write(new Buffer("c"))

That’s three calls to the I/O layer. Although you're using “buffers”, the data is not buffered. A buffered stream would do: fs.write(new Buffer ("abc")), one call to the I/O layer.

As of now, in Node.js v0.12 (stable version announced 02/06/2015) now supports two functions: cork() and uncork(). It seems that these functions will finally allow you to buffer/flush the write calls.

For example, in Java there are some classes that provide buffered streams (BufferedOutputStream, BufferedWriter...). If you write three bytes, these bytes will be stored in the buffer (memory) instead of doing an I/O call just for three bytes. When the buffer is full the content is flushed and saved to disk. This improves performance.

I'm not discovering anything, just remembering how a disk access should be done.

Solution 3

You can of course make it a little more advanced. Non-blocking, writing bits and pieces, not writing the whole file at once:

var fs = require('fs');
var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
  stream.write("My first row\n");
  stream.write("My second row\n");
  stream.end();
});

Solution 4

Synchronous Write

fs.writeFileSync(file, data[, options])

fs = require('fs');

fs.writeFileSync("foo.txt", "bar");

Asynchronous Write

fs.writeFile(file, data[, options], callback)

fs = require('fs');

fs.writeFile('foo.txt', 'bar', (err) => { if (err) throw err; });

Where

file <string> | <Buffer> | <URL> | <integer> filename or file descriptor
data <string> | <Buffer> | <Uint8Array>
options <Object> | <string>
callback <Function>

Worth reading the offical File System (fs) docs.

Update: async/await

fs = require('fs');
util = require('util');
writeFile = util.promisify(fs.writeFile);

fn = async () => { await writeFile('foo.txt', 'bar'); }

fn()

Solution 5

var path = 'public/uploads/file.txt',
buffer = new Buffer("some content\n");

fs.open(path, 'w', function(err, fd) {
    if (err) {
        throw 'error opening file: ' + err;
    }

    fs.write(fd, buffer, 0, buffer.length, null, function(err) {
        if (err) throw 'error writing file: ' + err;
        fs.close(fd, function() {
            console.log('file written');
        })
    });
});
Share:
1,849,015
Gjorgji
Author by

Gjorgji

Updated on July 22, 2022

Comments

  • Gjorgji
    Gjorgji almost 2 years

    I've been trying to find a way to write to a file when using Node.js, but with no success. How can I do that?

  • Anderson Green
    Anderson Green over 11 years
    I've tested this script using Node, and I tried changing the file path to "/home/", but I got the following error: { [Error: EACCES, open '/home/test.txt'] errno: 3, code: 'EACCES', path: '/home/test.txt' } How can I modify this script so that it will work outside of /tmp?
  • Scott Tesler
    Scott Tesler over 11 years
    What is the 'fd' variable passed into the callback for stream.once ?
  • Alexey Kamenskiy
    Alexey Kamenskiy over 11 years
    @ScottDavidTesler file descriptor so you will be able to close stream after you've done with it.
  • MetaGuru
    MetaGuru over 11 years
    When do I close the stream? Why is this non-blocking? Just curious, I am trying to write to a log file.
  • Fredrik Andersson
    Fredrik Andersson over 11 years
    You can always do a stream.end() when you've done your stream.writes(). I will add it to the example.
  • David Erwin
    David Erwin over 11 years
    Also note you can use fs.writeFileSync(...) to accomplish the same thing synchronously.
  • Automatico
    Automatico about 11 years
    Will this fail if the server goes down before stream.end() is called? In essence, can I use this for error logging to specific file? (Yes, I know you can specify this when you run the node app, but for certain errors I want to store it in a different file than all the other logging).
  • Fredrik Andersson
    Fredrik Andersson about 11 years
    I'm not sure if when the stream is flushed. My guess is that there is a possibility to flush the stream on demand.
  • Jo Liss
    Jo Liss over 10 years
    Does the 'open' event happen asynchronously? Do I have to wait for it, or can I start writing into the stream immediately?
  • Denys Vitali
    Denys Vitali over 10 years
    Maybe it's a bit old, but @AndersonGreen, you need to run node as root or chmod /home properly to allow R/W permissions to current node process owner (your username tough) so you can write the file
  • jane arc
    jane arc over 10 years
    Actually, @DenysVitali, the problem is that jane should not be able to write any files into /home/.... Generally that directory is 755 root:wheel (or whatever). If node wants to write a file as jane, it's going to be easier to write to /home/jane/test.txt. Changing /home to something more permissive than 755 is a huge mistake.
  • Denys Vitali
    Denys Vitali over 10 years
    @JaneAvriette Well, since he wanted to save the file on /home directory I suggested to chmod it. I know it could generate a security issue. But well, if the user wants to save there, that's the solution. P.S: I agree with what you said (:
  • Robbie Smith
    Robbie Smith almost 10 years
    I'm trying to do this to an ascii based file and null characters are getting inserted into every other character. Advice?
  • bryanmac
    bryanmac almost 10 years
    +1 - nice explanation. For write stream, it's important to read the docs carefully. If returns false or closing, important to call writer.once('drain', function(){}) or I missed lines that hadn't drained when the process ended.
  • professormeowingtons
    professormeowingtons almost 10 years
    any chance you could provide an example of how to use cork() and uncork() for those of us who want to try out the pre-release 0.11 node?
  • Fredrik Andersson
    Fredrik Andersson over 9 years
    @JoLiss You will have to wait for it.
  • Kai Feng Chew
    Kai Feng Chew over 9 years
    Where to find the file helloworld.txt ? I can't find it in any folders... thanks.
  • Sérgio
    Sérgio over 9 years
    in folder that you run the script
  • Kai Feng Chew
    Kai Feng Chew over 9 years
    That's weird... I just can't find it anywhere. Will it be hidden? thanks again~
  • Kai Feng Chew
    Kai Feng Chew over 9 years
    I just found it. Using this ROOT_APP_PATH = fs.realpathSync('.'); console.log(ROOT_APP_PATH); to get my where the file written. Thanks.
  • Sean Glover
    Sean Glover over 9 years
    this demonstrates how to write a file using lower level fs operations. for example, you can guarantee when the file has finished writing to disk and has released file descriptors.
  • aug
    aug about 9 years
    As of now, Node v0.12 is stable.
  • Adam Johns
    Adam Johns over 8 years
    Do you need to fs.close() when finished?
  • Green
    Green over 7 years
    This modules is created to save and remove files.. Not an answer.
  • nasch
    nasch about 7 years
    At least with ECMAScript 6, fs.writeFile is deprecated. Not sure what has replaced it.
  • Ravi Shanker Reddy
    Ravi Shanker Reddy about 7 years
    Where you are writting the data into the "to.text"??
  • Константин Ван
    Константин Ван over 6 years
  • Freewalker
    Freewalker over 6 years
    Or ES2015 async/await style: await promisify(fs.writeFile)("./test.md", markdownFile);
  • Amir
    Amir over 5 years
    @Sérgio: do we need to close writefile? I am calling another process and I am receiving an error msg regarding file is begin used by some other process.
  • Tamer
    Tamer about 5 years
    single quote in the string should be escaped.
  • Ron Jensen
    Ron Jensen about 5 years
    This example is leaving me with an empty "my_file.txt" and a dump of the WriteStream object.
  • drorw
    drorw about 5 years
    According to an analysis of code from GitHub, fs.writeFile seems to be the most popular of the functions you mentioned. Here are real world examples for using fs.writeFile
  • TrevTheDev
    TrevTheDev about 5 years
    @jgraup: are you using the latest version of node?
  • jgraup
    jgraup about 5 years
    Node v10.15.0
  • TrevTheDev
    TrevTheDev about 5 years
    @jpraup - latest is Node 12.
  • jgraup
    jgraup about 5 years
    I would just add the requirements in your answer or a note about the warning. The docs say Added in: v10.0.0 so I would assume it could be used but I see elsewhere on here that people have opted to suppress the warning.
  • nponeccop
    nponeccop about 5 years
    Are there production quality libraries on npm implementing buffered writing?
  • lte__
    lte__ almost 5 years
    I'm trying to do this but I get Uncaught ReferenceError: require is not defined...
  • Zimano
    Zimano over 4 years
    Enclosing function has to be async or this will not work.
  • Zimano
    Zimano over 4 years
    Why are these snippets and not pieces of code? They will never be able to run in a browser anyways.
  • Timo Ernst
    Timo Ernst over 4 years
    It's always refreshing to see how easy this is using Node compared to languages like Java #FileOutputStreamWhatEverIntefaceBlah
  • Dan Dascalescu
    Dan Dascalescu over 4 years
    This introduces all sorts of complications (MongoClient, JSON etc.) that do not pertain to the question.
  • Dan Dascalescu
    Dan Dascalescu over 4 years
    createWriteStream was already mentioned in multiple answer years before this one.
  • Dan Dascalescu
    Dan Dascalescu over 4 years
    What does this answer add to the multiple already existing answers about writeFile?
  • Dan Dascalescu
    Dan Dascalescu over 4 years
    writeFile had already been given as an answer multiple times, years ago. What does this answer add?
  • Michal
    Michal over 4 years
    Also why od you open file? Shouldn't the answer be about writing files?
  • Manfred
    Manfred over 4 years
    Since in this example the offset if set to '0' (= third parameter of fs.write()) this example works only if everything is short enough to be written in a single write call.
  • Manfred
    Manfred over 4 years
    Since it's now available I'd recommmend using const instead of var, i.e. const fs = require('fs');, to avoid unwanted side effects, in particular if you are working with a somewhat larger code base.
  • Manfred
    Manfred over 4 years
    @Zimano As I understand it the question was regarding nodejs so doesn't need to be able to run in a browser.
  • Zimano
    Zimano over 4 years
    @Manfred Exactly! I think you misunderstood what I was trying to say; there is no point in having snippets since it is nodejs!
  • wintercounter
    wintercounter about 4 years
    @Zimano Node already has support for top-level await, you don't need async wrapper.
  • Alex G
    Alex G almost 3 years
    I have tested createWriteStream on nodejs 14 and it is a lot faster than individual writes. also cork and uncork didn't affect the performance.
  • Elliott Jones
    Elliott Jones almost 3 years
    @lte_ What environment are you running it in? If you're running it in the browser you'll definitely get that error. the answer here explains it best.