Файловая система: чтение и запись (модуль fs)

Как Node читает и пишет файлы — то, чего браузерному JS недоступно.

Модуль fs (file system) — встроенный модуль Node для работы с файлами: чтения, записи, создания и удаления.

Чтение файла

Базовая операция — прочитать содержимое файла. Асинхронный вариант принимает колбэк (error-first), который сработает, когда файл прочитан:

const fs = require("fs");

fs.readFile("note.txt", "utf8", (err, data) => {
  if (err) {
    console.error("Не удалось прочитать:", err.message);
    return;
  }
  console.log("Содержимое файла:", data);
});

Второй аргумент "utf8" важен: без него вернутся «сырые» байты (Buffer), а с ним — нормальная строка. Код использует fs, поэтому исполняется только в Node.

Запись файла

Запись перезаписывает файл целиком (создаёт, если его нет):

const fs = require("fs");

fs.writeFile("output.txt", "Привет из Node!", (err) => {
  if (err) {
    console.error("Ошибка записи:", err.message);
    return;
  }
  console.log("Файл сохранён");
});

Чтобы дописать в конец, а не перезаписать, есть fs.appendFile.

Версия на промисах — современнее

У fs есть вариант с промисами — fs/promises. С ним удобно использовать async/await и не плодить колбэки:

const fs = require("fs/promises");

async function main() {
  await fs.writeFile("data.txt", "строка 1\n");
  await fs.appendFile("data.txt", "строка 2\n");
  const text = await fs.readFile("data.txt", "utf8");
  console.log(text);
}

main();

Это рекомендуемый стиль для нового кода: читается линейно, ошибки ловятся через try/catch.

Sync против async — осторожно

У многих функций fs есть синхронный близнец с суффиксом Sync: fs.readFileSync, fs.writeFileSync. Он возвращает результат сразу, но блокирует поток до конца операции:

Асинхронный (readFile)Синхронный (readFileSync)
не блокирует — поток свободенблокирует поток до конца
результат в колбэке/промисерезультат сразу из функции
для серверов и продакшенадля скриптов и старта приложения

Правило: в веб-сервере используйте асинхронные версии — синхронная заблокирует обработку всех запросов, пока читается файл. Sync уместен в небольших скриптах и при старте (например, прочитать конфиг один раз).

Содержимое файла — это просто строка

После чтения текст файла — обычная строка, и дальше это чистый JavaScript. Например, посчитать строки и слова:

const fileText = "первая строка\nвторая строка\nтретья";

const lines = fileText.split("\n");
const words = fileText.split(/\s+/);

console.log("Строк:", lines.length);
console.log("Слов:", words.length);

Вывод:

Строк: 3
Слов: 5

Итог

  • fs.readFile читает файл, fs.writeFile записывает (перезаписывая).
  • Указывайте кодировку "utf8", иначе получите Buffer вместо строки.
  • fs/promises + async/await — рекомендуемый современный стиль.
  • Синхронные *Sync-версии блокируют поток — не используйте их в серверах.
Проверьте себя
1. Что вернёт fs.readFile без указания кодировки 'utf8'?
AСтроку
BBuffer (сырые байты)
CОшибку
Dnull
2. Почему синхронные *Sync-функции опасны в веб-сервере?
AОни медленнее работают с диском
BОни блокируют единственный поток, останавливая обработку всех запросов
CОни не умеют читать большие файлы
DОни не возвращают результат
3. Какой модуль даёт промис-версию файловых операций?
Afs/promises
Bfs-async
Cpromise-fs
Dfs.then
Поддержать проект