Гид по технологиям

Запись файлов в Node.js: writeFile, appendFile и потоки

4 min read Node.js Обновлено 20 Nov 2025
Запись файлов в Node.js: writeFile, appendFile, потоки
Запись файлов в Node.js: writeFile, appendFile, потоки

Человек в белой рубашке пишет в блокноте

Краткое описание методов

  • writeFile — записывает данные в файл; по умолчанию заменяет содержимое.
  • appendFile — добавляет данные в конец файла.
  • createWriteStream — создаёт записываемый поток; подходит для больших файлов и последовательной записи.

Важно: термин “поток” (stream) — это последовательность данных, которую можно читать или записывать частями, не загружая весь файл в память.

Использование writeFile()

writeFile() — самый простой способ записать файл в Node.js.

const fs = require("fs");

fs.writeFile("test.txt", "New content", err => {
  if (err) {
    console.log(err);
  }
});

Async/await версия через промисы:

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

async function writeToFile() {
  try {
    await fs.writeFile("test.txt", "New cont");
  } catch (err) {
    console.log(err);
  }
}

writeToFile();

По умолчанию writeFile заменяет содержимое файла. Можно задать флаг, чтобы изменить поведение:

  • r+ — открыть для чтения и записи.
  • w+ — открыть для чтения и записи, обрезав файл.
  • a — открыть для записи в конец файла.
  • a+ — открыть для чтения и записи в конец файла.

Пример использования флага a+:

const fs = require("fs");

fs.writeFile("test.txt", "Newer content", { flag: "a+" }, err => {
  if (err) {
    console.log(err);
  }
});

Существует также синхронная версия writeFileSync:

const fs = require("fs");

fs.writeFileSync("test.txt", "Newer content", { flag: "a+" });

(Для синхронных вызовов исключения следует обрабатывать через try/catch.)

Использование createWriteStream()

Если файл большой или вы получаете данные по частям, потоковая запись предпочтительнее: она не требует загрузки всего содержимого в память.

Создание записываемого потока:

const fs = require("fs");

// create a writable stream
let writableStream = fs.createWriteStream("test.txt");

// Запись в файл через поток
writableStream.write("New content");
// Не забывайте закрыть поток, когда закончите
writableStream.end();

Пример использования pipe: перенаправление ввода терминала в файл:

const fs = require("fs");
let writableStream = fs.createWriteStream("test.txt");
process.stdin.pipe(writableStream);

Для остановки из терминала обычно используют Ctrl+D или Ctrl+C.

Копирование файла через потоки (чтение — запись):

const fs = require("fs");
let readableStream = fs.createReadStream("test.txt");
let writableStream = fs.createWriteStream("test2.txt");

readableStream.on("data", function(chunk) {
  writableStream.write(chunk);
});

readableStream.on("end", function() {
  writableStream.end();
});

Использование appendFile()

appendFile() — простой способ добавить данные в конец файла:

const fs = require("fs");

fs.appendFile("test.txt", "added content", err => {
  if (err) {
    console.error(err);
  }
});

Async/await через промисы:

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

async function appendToFile() {
  try {
    await fs.appendFile("test.txt", "added content");
  } catch (err) {
    console.log(err);
  }
}

appendToFile();

Синхронная версия:

const fs = require("fs");
fs.appendFileSync("test.txt", "added content");

Когда выбирать тот или иной метод

  • Маленькие файлы (< несколько мегабайт) и простые операции: writeFile / appendFile. Простая реализация, понятная обработка ошибок.
  • Большие файлы, потоковый ввод/вывод, конвейеры (pipeline): createWriteStream. Экономия памяти и возможность контроля потока данных.
  • Нужна атомарная запись или блокировка доступа: рассматривайте дополнительные модули/библиотеки для атомарных операций (fs.rename/временные файлы).

Important: для серверных приложений избегайте частых синхронных вызовов в основном потоке — они блокируют event loop.

Сравнительная таблица

МетодКогда подходитПлюсыМинусы
writeFile / writeFileSyncМалые файлы и одноразовые записиПростотаПотребляет память для полного содержимого; sync блокирует loop
appendFile / appendFileSyncДобавление в конец файлаПростота добавленияТо же ограничение по памяти в async варианте при больших буферах
createWriteStreamБольшие файлы, потоковая записьПамять экономится; поддержка backpressureТеперь нужно управлять событиями/закрытием потока

Модель принятия решения (Mermaid)

flowchart TD
  A[Нужно записать данные?] --> B{Данные маленькие?}
  B -- Да --> C[writeFile или appendFile]
  B -- Нет --> D{Данные приходят частями?}
  D -- Да --> E[createWriteStream]
  D -- Нет --> F[Разбить на чанки или использовать поток]
  C --> G[Проверьте флаги и обработку ошибок]
  E --> G
  F --> G

Роль‑ориентированный чеклист

Для разработчика:

  • Выбрать метод по размеру данных и частоте записей.
  • Обработать ошибки (callback/try-catch/параметры событий).
  • Закрыть поток (writable.end()).

Для DevOps:

  • Мониторить использование диска и I/O.
  • Настроить логирование и ротацию файлов при необходимости.

Для архитектора:

  • Принять решение об атомарности и согласованности данных.
  • Оценить потребности в резервировании и бэкапах.

Памятка: быстрые примеры

Записать JSON файл асинхронно:

const fs = require("fs").promises;
async function saveJson(file, obj) {
  await fs.writeFile(file, JSON.stringify(obj, null, 2));
}

Потоковое сохранение больших данных:

const fs = require("fs");
const stream = fs.createWriteStream("bigfile.bin");
// Получаем чанки (например, от сети) и вызываем stream.write(chunk);
// в конце stream.end();

Копирование с использованием pipe (рекомендуемый паттерн):

const fs = require("fs");
fs.createReadStream("source.txt").pipe(fs.createWriteStream("dest.txt"));

Контрпримеры и когда методы не подходят

  • writeFile не подходит, если файл > доступной оперативной памяти.
  • Синхронные версии неприемлемы в высоконагруженных серверах.
  • Для файлов, требующих атомарной замены, простая запись в существующий файл может привести к непоследовательности при сбоях — используйте временные файлы + переименование.

Критерии приёмки

  • Файл создаётся/обновляется без ошибок в типичных сценариях.
  • Для потоков: данные полностью попадают в файл и поток корректно закрывается.
  • Для append: данные добавляются в конец, порядок сохраняется.
  • Нагрузочные тесты показывают приемлемое потребление памяти и времени.

Однострочный глоссарий

  • stream — последовательность данных, читаемая/записываемая частями; backpressure — механизм замедления потока для синхронизации producer/consumer.

Резюме

writeFile и appendFile удобны для небольших и простых операций; createWriteStream обязателен при работе с большими объёмами или потоковыми источниками. Всегда обрабатывайте ошибки, выбирайте асинхронные API для неблокирующих приложений и закрывайте потоки для корректного завершения записи.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Сброс пароля iPhone и iPad — подробное руководство
Mobile

Сброс пароля iPhone и iPad — подробное руководство

Сброс пароля в React и Express — пример и рекомендации
Authentication

Сброс пароля в React и Express — пример и рекомендации

Изменить пароль Windows через net user
Windows

Изменить пароль Windows через net user

Исправить iPhone Unavailable — 4 проверенных способа
Мобильные устройства

Исправить iPhone Unavailable — 4 проверенных способа

Разблокировать отключённый iPhone — 4 метода
Mobile

Разблокировать отключённый iPhone — 4 метода

Безпарольный вход в Microsoft — как настроить
Безопасность

Безпарольный вход в Microsoft — как настроить