NoNode.js · Lesson 2 of 7

File System

Node's `fs` module gives you full control over the file system. The promises API (`fs/promises`) is the modern way — no callbacks needed.

JavaScript
import { readFile, writeFile, appendFile,
          readdir, mkdir, stat, unlink } from 'fs/promises'
import { existsSync } from 'fs'

// Read a file
const text = await readFile("data.txt", "utf-8")
console.log(text)

// Write a file (overwrites if exists)
await writeFile("output.txt", "Hello, file system!\n")

// Append to a file
await appendFile("log.txt", `[${new Date().toISOString()}] Event logged\n`)

// Read directory
const files = await readdir(".")
console.log(files.filter(f => f.endsWith(".txt")))

// Create directory (nested)
await mkdir("data/2024/reports", { recursive: true })

// File info
const info = await stat("data.txt")
console.log(info.size)         // bytes
console.log(info.mtime)        // last modified
console.log(info.isDirectory()) // false

// Check existence without throwing
if (existsSync("config.json")) {
  const config = JSON.parse(await readFile("config.json", "utf-8"))
}

// Delete a file
await unlink("temp.txt")
JavaScript
import { createReadStream, createWriteStream } from 'fs'
import { pipeline } from 'stream/promises'
import { createGzip } from 'zlib'

// Streams — for large files that don't fit in memory
// pipeline() handles backpressure and cleanup automatically
await pipeline(
  createReadStream("huge-file.txt"),
  createGzip(),
  createWriteStream("huge-file.txt.gz")
)
console.log("Compressed!")

// Reading a large file line by line
import { createInterface } from 'readline'

async function* readLines(path) {
  const rl = createInterface({
    input: createReadStream(path),
    crlfDelay: Infinity,
  })
  for await (const line of rl) {
    yield line
  }
}

let count = 0
for await (const line of readLines("huge-file.txt")) {
  if (line.includes("ERROR")) {
    count++
    console.log(line)
  }
}
console.log(`Found ${count} errors`)
✦ Tip
Use streams (`createReadStream`, `pipeline`) for files larger than ~50MB. Reading the whole file into memory with `readFile` will fail or slow down on large inputs. The `readline` interface combined with `for await` is the idiomatic way to process files line by line.