Mastering Node.js File System: From Streams to Stats
- Writing Files
1.1 Asynchronous writeFile
const fs = require('fs');
fs.writeFile('./motto.txt', 'When three walk together, one can be my teacher.', err => {
if (err) {
console.error(err);
return;
}
console.log('File written');
});
1.2 Synchronous writeFileSync
try {
fs.writeFileSync('./motto.txt', 'When three walk together, one can be my teacher.');
} catch (e) {
console.error(e);
}
1.3 Apending Data
// async append
fs.appendFile('./motto.txt', '\nChoose the good and follow it, correct the bad.', err => {
if (err) throw err;
console.log('Appended');
});
// sync append
fs.appendFileSync('./motto.txt', '\nReview the old to know the new.');
1.4 Streaming Writes with createWriteStream
const ws = fs.createWriteStream('./poem.txt');
ws.write('A square pond like a mirror unfolds,\r\n');
ws.write('Clouds and light wander together.\r\n');
ws.write('Why is the water so clear?\r\n');
ws.write('Because fresh springs keep flowing.\r\n');
ws.end();
- Reading Files
2.1 Asynchronous readFile
fs.readFile('./motto.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
2.2 Synchronous readFileSync
const buffer = fs.readFileSync('./motto.txt');
const text = fs.readFileSync('./motto.txt', 'utf8');
2.3 Streaming Reads with createReadStream
const rs = fs.createReadStream('./poem.txt');
rs.on('data', chunk => {
console.log(chunk.toString());
});
rs.on('end', () => {
console.log('Read finished');
});
- Copy, Move, and Rename
3.1 Copying Files
// memory-heavy approach
const data = fs.readFileSync('./movie.mp4');
fs.writeFileSync('./movie-copy.mp4', data);
// stream approach
const rs = fs.createReadStream('./movie.mp4');
const ws = fs.createWriteStream('./movie-copy2.mp4');
rs.pipe(ws);
3.2 Move / Rename
fs.rename('./poem.txt', './short-poem.txt', err => {
if (err) throw err;
console.log('Renamed');
});
fs.renameSync('./motto.txt', './my-motto.txt');
- Deleting Files
fs.unlink('./temp.log', err => {
if (err) throw err;
console.log('Deleted');
});
fs.unlinkSync('./old.db');
- Diretcory Operations
5.1 Creating Directories
// single
fs.mkdir('./docs', err => {
if (err) throw err;
});
// nested
fs.mkdir('./a/b/c', { recursive: true }, err => {
if (err) throw err;
});
fs.mkdirSync('./x/y/z', { recursive: true });
5.2 Reading Directories
fs.readdir('./a', (err, files) => {
if (err) throw err;
console.log(files);
});
const list = fs.readdirSync('./x');
5.3 Removing Directories
fs.rmdir('./docs', err => {
if (err) throw err;
});
fs.rmdir('./a', { recursive: true }, err => {
if (err) throw err;
});
fs.rmdirSync('./x', { recursive: true });
- Inspecting File Stats
fs.stat('./my-motto.txt', (err, stats) => {
if (err) throw err;
console.log(stats);
console.log('Is file?', stats.isFile());
console.log('Size (bytes):', stats.size);
});
const info = fs.statSync('./my-motto.txt');
- Path Handling
Relative paths are resolved against the process working directory, not the script loaction. To avoid surprises, always build absolute paths with __dirname:
const path = require('path');
const data = fs.readFileSync(path.join(__dirname, 'data.txt'));