Style - How to write meaningful comments
File I/O (Input/Output) lets your programs read from and write to files on your computer. This enables data persistence: your program can save data and reload it later.
Node.js provides the fs (filesystem) module for file operations. We'll focus on synchronous methods, which pause your program until the file operation completes.
import fs from 'node:fs';
// Synchronous - waits for file to be read
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
console.log('This runs after reading');
<aside> 💡
"Synchronous" means blocking: your code waits.
</aside>
import fs from 'node:fs';
// Read entire file as string
const content = fs.readFileSync('data.txt', 'utf8');
console.log(content);
// Without 'utf8', returns Buffer (raw bytes)
const buffer = fs.readFileSync('data.txt');
console.log(buffer); // <Buffer 48 65 6c 6c 6f>
Parameters:
'utf8' for text files)Common use cases:
// Read configuration
const config = fs.readFileSync('config.txt', 'utf8');
// Read user data
const users = fs.readFileSync('users.txt', 'utf8');
// Process line by line
const lines = fs.readFileSync('data.txt', 'utf8').split('\\\\n');
for (const line of lines) {
console.log(line);
}
<aside> ⌨️
Hands on: Create a file called message.txt with some text. Write code to read and print its contents.
</aside>
Check if a file exists before reading:
if (fs.existsSync('data.txt')) {
const data = fs.readFileSync('data.txt', 'utf8');
console.log(data);
} else {
console.log('File not found');
}
import fs from 'node:fs';
// Write string to file (overwrites existing content)
fs.writeFileSync('output.txt', 'Hello, World!');
// Write multiple lines
const lines = ['Line 1', 'Line 2', 'Line 3'];
fs.writeFileSync('output.txt', lines.join('\\\\n'));
Important: writeFileSync() overwrites the entire file. Previous content is lost.
// Example: save user data
const user = {
name: 'Alice',
age: 28
};
fs.writeFileSync('user.txt', JSON.stringify(user, null, 2));
<aside> ⚠️
Always include error handling (covered in upcoming sections) when working with files. File operations can fail if the file doesn't exist, lacks permissions, or the disk is full.
</aside>
Add content to the end of a file without erasing existing content:
import fs from 'node:fs';
// Append to existing file
fs.appendFileSync('log.txt', 'New log entry\\\\n');
// Create file if it doesn't exist
if (!fs.existsSync('notes.txt')) {
fs.writeFileSync('notes.txt', '');
}
fs.appendFileSync('notes.txt', 'First note\\\\n');
fs.appendFileSync('notes.txt', 'Second note\\\\n');
Common use case - logging:
function log(message) {
const timestamp = new Date().toISOString();
fs.appendFileSync('app.log', `[${timestamp}] ${message}\\\\n`);
}
log('Application started');
log('User logged in');
log('Error occurred');
// Relative to current working directory
fs.readFileSync('data.txt', 'utf8');
fs.readFileSync('./data.txt', 'utf8');
fs.readFileSync('../data.txt', 'utf8');
// Absolute path
fs.readFileSync('/Users/alice/projects/data.txt', 'utf8');
fs.readFileSync('C:\\\\\\\\Users\\\\\\\\alice\\\\\\\\projects\\\\\\\\data.txt', 'utf8'); // Windows
__dirname gives the directory of the current file (not the working directory):
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
// In ES modules, we need to recreate __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Build path relative to script location
const filePath = path.join(__dirname, 'data.txt');
const data = fs.readFileSync(filePath, 'utf8');
// Nested folders
const configPath = path.join(__dirname, 'config', 'settings.txt');
<aside> 💡
Use path.join() to build paths—it handles different operating systems automatically (/ on Mac/Linux, \ on Windows).
</aside>
import fs from 'node:fs';
const todos = ['Buy groceries', 'Walk dog', 'Write code'];
// Save todos
fs.writeFileSync('todos.txt', todos.join('\\\\n'));
// Load todos
const loadedTodos = fs.readFileSync('todos.txt', 'utf8').split('\\\\n');
console.log(loadedTodos);
import fs from 'node:fs';
const text = fs.readFileSync('article.txt', 'utf8');
const words = text.split(/\\\\s+/); // Split on whitespace
const wordCount = words.length;
console.log(`Word count: ${wordCount}`);
fs.writeFileSync('word-count.txt', `Total words: ${wordCount}`);
import fs from 'node:fs';
function backup(filename) {
if (fs.existsSync(filename)) {
const content = fs.readFileSync(filename, 'utf8');
const backupName = `${filename}.backup`;
fs.writeFileSync(backupName, content);
console.log(`Backed up ${filename} to ${backupName}`);
}
}
backup('important-data.txt');
<aside> ⌨️
Hands on: Create a program that reads a text file, counts how many times the word "JavaScript" appears, and writes the count to a new file.
</aside>
import fs from 'node:fs';
// 1. Read
const input = fs.readFileSync('input.txt', 'utf8');
// 2. Process
const processed = input.toUpperCase();
// 3. Write
fs.writeFileSync('output.txt', processed);
import fs from 'node:fs';
// Read all lines
const lines = fs.readFileSync('data.txt', 'utf8').split('\\\\n');
// Filter empty lines
const nonEmpty = lines.filter(line => line.trim() !== '');
// Process each line
const processed = nonEmpty.map(line => line.trim().toUpperCase());
// Write back
fs.writeFileSync('cleaned.txt', processed.join('\\\\n'));
| Method | Purpose | Overwrites? |
|---|---|---|
readFileSync(path, encoding) |
Read entire file | - |
writeFileSync(path, data) |
Write to file | Yes |
appendFileSync(path, data) |
Add to end of file | No |
existsSync(path) |
Check if file exists | - |

Found a mistake or have a suggestion? Let us know in the feedback form.