Categories
nodejs

Reading from and writing to files in node.js

NodeJS is an awesome platform to build applications in javascript which can run on the server.
It allows you to read n write to files asynchronously and synchronously

Writing Data to files

The easiest way would be write synchronously (i.e. wait till the writing operating is finished)

var fs = require('fs');
fs.writeFileSync('/path/to/some_text.txt', 'some text');

But the preferable way of writing to files will be asynchronous in context of web apps.

var fs = require('fs');
fs.writeFile("/path/to/some_text.txt", "test data!", function(err) {
    if(err) {
        console.log(err);
    } else {
        console.log("file has been saved successfully");
    }
});

In this case the program will continue to execute next instruction without waiting for the file write to complete. Once the file writing is completed, the third parameter (closure ) is executed. Above method overwrite the current file. So if you want to append the data, use

appendFile

(async) and

appendFileSync

for synchronous appending data to file.

Reading Files

Like writing you can read files

synchronously
var FS =  require ( 'FS' ); 
var text = FS . readFileSync ( 'path/to/test_text.txt' ,  'utf8' );

As you can guess the second parameter here is the encoding. If it is not passed the function returns a

buffer

For reading

asynchronously
fs.readFile('path/to/test.txt', {encoding: 'utf8'}, function (err, data) {
    if (err) throw err;
    console.log(data);
});

Similar to the synchronous function you need to pass the encoding, otherwise you get the data buffer instead of text.

Optimizing reading and writing using File Streams / threads

Log files or other automatically generated files normally are of few mbs in size and can even reach Gb. Above functions

readFile

and

writeFile

works well for small files but becomes bottleneck when the filesize grows large because both of above methods load all the content of the file into memory. Threads/Streams come to our rescue when we need to deal with larger files.

var fs = require('fs');
var stream = fs.createReadStream('path/to/test.txt', {encoding: 'utf8'});
stream.on('readable', function() {
    var buf;
    while ((buf = stream.read()) !== null) {
        console.log(buf);
    }
});

Stream.once( 'end' ,  function ()  { 
    console.Log( 'Read completed successfully.' ); 
});

The above function opens the file and when the file is ready to be read, the event

readable

is fired, and code in the

closure

is executed which reads the file till the end. Here we are only reading few bytes / kbs of data from the file at a time. You can customize this by passing no of bytes to read as

stream.read(2048)

Now for writing to files with streams

var fs = require('fs');
var writer = fs.createWriteStream('test.txt', {flags: 'w'});
writer.on('finish', function() {
    console.error('data has been saved successfully');
});
var i = 0;
function write() {
    do {
        var ok = writer.write('test, #' + i + '!\n');
        if (!ok) {
            writer.once('Drain', write);
            break;
        }
        i++;
    } while (i < 10 && ok);
    if (i === 10) {
        writer.end('===== end =====\n');
    }
}
write();

The above code writes to the file 10 lines. When it is not successful, it schedules a listener to wait for event

Drain

which indicates that the file is writeable and writes the data.

We can use read & write data streams to copy data from one file to another using the stream property

pipe

which can be called on the source stream (reader) and pass the target stream writer as input to save data.

var fs = require('fs');
var source = fs.createReadStream('file1.txt');
var target = fs.createWriteStream('file2.txt');
source.pipe(target);

In the above code we save the data in

file2.txt

as soon as we read data from

file1.txt

Now if you need to transform/change the data while copying you can use the

Transform

function of the

Stream

in combination with

pipe

.

var fs = require('fs');
var Transform = require('stream').Transform;

var uppercase = new Transform({decodeStrings: false});
uppercase._transform = function(chunk, encoding, done) {
  done(null, chunk.toUpperCase());
};

var source = fs.createReadStream('file1.txt', {encoding: 'utf8'});
var target = fs.createWriteStream('file2.txt');
source.pipe(uppercase).pipe(target);

The above code transforms the text in

file1.txt

to

uppercase

and saves in

file2.txt

Thats all for now folks. This is as broad as we can cover in a single tutorial. Hope this helps. For more information please visit the official documentation.

Ref: Чтение и запись файлов в NodeJS
http://nodejs.org/api/fs.html