Read Files
(This is part of a brief series on the fs module)
Reading Files Syncrhonously
The readFileSync
method of the fs
module can be used to read files from disk:
const { readFileSync } = require('fs');
const FILE_TO_READ = './../some-file.txt';
const contents = readFileSync(FILE_TO_READ);
The default behavior is that the returned content is a buffer.
To convert the content to a more understandable string within the same line of code, an "encoding" option could be passed:
const { readFileSync } = require('fs');
const FILE_TO_READ = './../some-file.txt';
const contents = readFileSync(FILE_TO_READ, { encoding: 'utf8' });
Keeping The Even Loop Open With Callback
The readFile
method of the fs
module can be used to read files from disk:
const { readFile } = require('fs');
const FILE_TO_READ = './../small-file.txt';
function readFileCallback(err, contents){
if (err) {
console.error(err);
return;
}
console.log('done reading: '),
console.log(contents)
}
readFile(FILE_TO_READ, readFileCallback);
The default behavior is that the returned content is a buffer of the file contents.
To convert the content to a more understandable string, an "encoding" option could be passed to the readFile
function argument list:
const { readFile } = require('fs');
const FILE_TO_READ = './../small-file.txt';
function readFileCallback(err, contents){
if (err) {
console.error(err);
return;
}
console.log('done reading: '),
console.log(contents)
}
readFile(FILE_TO_READ, { encoding: 'utf8' }, readFileCallback);
Keeping The Event Loop Open with The Promise API
the node fs module has a nice built-in promise-syntax api:
const { readFile } = require('fs/promises');
const FILE_TO_READ = './../small-file.txt';
// NOTE: the optional {encoding: utf8}
// parses the file as a string
// the default, without the encoding, returns a buffer
readFile(FILE_TO_READ, { encoding: 'utf8' })
.then((data) => {
console.log(data);
})
.catch(console.log);
Stream File Data With createReadStream
This is a trivial example of using one of node's built-in stream apis. There is a bunch of more helpful info to consider about streams, but this will just cover a few things.
const { createReadStream } = require('fs');
const FILE_TO_READ = './../big-file.txt';
let chunkCount = 0;
const readStream = createReadStream(FILE_TO_READ)
readStream.on('data', (d) => {
chunkCount++;
console.log({chunkCount})
})
Adjust The Chunk Size
the createReadStream
api gives a few options to use.
One of the options is called the highWaterMark
, which describes a limit on the of memory each chunk will consume. The node docs say the default value for the highWaterMark
is 64 * 1024
.
const { createReadStream } = require('fs');
const FILE_TO_READ = './../big-file.txt';
let chunkCount = 0;
const readStream = createReadStream(FILE_TO_READ)
readStream.on('data', (d) => {
chunkCount++;
})
readStream.on('end', () => {
console.log({ chunkCount });
})
Lets say the big-file.txt
is 190M
in size. The default number of chunks will be 3040
.
Let's update the process to have a smaller highWaterMark
and more break up the file stream into more chunks:
const { createReadStream } = require('fs');
const FILE_TO_READ = './../big-file.txt';
const DEFAULT_WATER_MARK = 64 * 1024;
let chunkCount = 0;
const readStream = createReadStream(FILE_TO_READ, { highWaterMark: DEFAULT_WATER_MARK * 2 });
readStream.on('data', (d) => {
chunkCount++;
})
readStream.on('end', () => {
console.log({ chunkCount });
})
Here, the number of chunks will be 1520
. Each chunk, now, is allowed to be 2x the size!