JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Запись файлов: fs.writeFil...

Запись файлов: fs.writeFile, fs.writeFileSync

Модуль 4: Node.js, Next.js и Angular
3 уровень , 2 лекция
Открыта

1. Введение

В реальных приложениях запись в файл нужна постоянно: сохранять результаты работы, логи, пользовательские данные, кэш, настройки и многое другое. Если вы когда-нибудь писали заметку в текстовый редактор или сохраняли картинку из Paint, то вы уже пользовались записью в файл — просто не через Node.js. Теперь мы научимся делать это программно.

Node.js предоставляет нам два основных метода для записи файлов:

  • fs.writeFile — асинхронный метод (рекомендуется для большинства случаев)
  • fs.writeFileSync — синхронный метод (для простых скриптов и особых случаев)

Оба этих метода позволяют создать новый файл или перезаписать существующий. Если файл не существует — он будет создан. Если существует — его содержимое будет полностью заменено новым. (Осторожно: старые данные исчезнут — как будто вы залили новый чай в уже наполненную чашку, не вылив старый. Надо быть аккуратнее!)

2. fs.writeFile: асинхронная запись

Синтаксис

fs.writeFile(path, data, [options], callback)
  • path — путь к файлу (строка или Buffer)
  • data — что записываем (строка или Buffer)
  • options — объект с настройками (необязателен)
  • callback — функция, которая вызовется по завершении (обязательна!)

Пример: создаём файл с приветствием

const fs = require('fs');

fs.writeFile('hello.txt', 'Привет, мир!', (err) => {
  if (err) {
    console.error('Ошибка при записи файла:', err);
  } else {
    console.log('Файл успешно записан!');
  }
});

Что тут происходит?
Node.js начинает записывать строку 'Привет, мир!' в файл hello.txt. Как только операция завершится (успешно или с ошибкой), вызывается функция-обработчик. Если всё прошло хорошо — увидим сообщение об успехе. Если что-то пошло не так (например, нет прав на запись) — ошибка попадёт в err.

Асинхронность: почему это важно?

Вспомните: Node.js работает в одном потоке, и если вы будете долго писать в файл синхронно, всё приложение «замрёт». Асинхронный метод позволяет продолжать выполнять другие задачи, пока файл записывается. Это особенно важно для серверов, которые должны быстро отвечать на запросы.

3. fs.writeFileSync: синхронная запись

Синтаксис

fs.writeFileSync(path, data, [options])
  • Всё как у асинхронного варианта, только без колбэка
  • Если что-то пошло не так — будет выброшено исключение (try/catch наше всё!)

Пример: записываем файл синхронно

const fs = require('fs');

try {
  fs.writeFileSync('hello_sync.txt', 'Синхронная запись!');
  console.log('Файл записан синхронно!');
} catch (err) {
  console.error('Ошибка при записи файла:', err);
}

Здесь всё просто: если запись прошла успешно — увидим сообщение, если нет — поймаем ошибку через catch. Но помните: пока файл пишется, Node.js не делает больше ничего! Поэтому используем этот метод только в коротких скриптах или там, где блокировка не страшна (например, в миграциях или CLI-утилитах).

4. Практика: сохраняем заметки пользователя

Давайте продолжим развивать наше учебное приложение — простую консольную заметочную книжку. На прошлой лекции мы научились читать файл с заметками. Теперь реализуем функцию сохранения новой заметки.

Шаг 1. Добавим функцию для записи новой заметки

const fs = require('fs');
const path = require('path');

const NOTES_FILE = path.join(__dirname, 'notes.txt');

function addNote(note, callback) {
  // Сохраняем заметку в конец файла, добавляя перевод строки
  fs.appendFile(NOTES_FILE, note + '\n', (err) => {
    if (err) {
      callback(err);
    } else {
      callback(null);
    }
  });
}

Внимание: Здесь мы используем fs.appendFile, чтобы не перезаписывать файл целиком, а добавлять новые заметки в конец. Но если вы хотите полностью заменить содержимое файла, используйте fs.writeFile.

Шаг 2. Используем функцию

addNote('Купить молоко', (err) => {
  if (err) {
    console.error('Не удалось сохранить заметку:', err);
  } else {
    console.log('Заметка сохранена!');
  }
});

Шаг 3. Проверяем результат

Если вы откроете файл notes.txt, увидите в нём вашу новую заметку. Каждый вызов addNote добавляет строку в конец файла.

5. Передача опций: кодировка, флаги, права доступа

Методы fs.writeFile и fs.writeFileSync принимают третий необязательный параметр — объект опций. Самые часто используемые:

  • encoding — кодировка (по умолчанию 'utf8')
  • mode — права доступа (по умолчанию 0o666)
  • flag — как открывать файл ('w' — запись, 'a' — добавление, и др.)

Пример: записываем файл в другой кодировке

fs.writeFile('data.txt', 'Данные в windows-1251', { encoding: 'windows-1251' }, (err) => {
  if (err) throw err;
  console.log('Файл сохранён в кодировке windows-1251!');
});

Пример: добавляем в файл (флаг 'a')

fs.writeFile('log.txt', 'Запись лога\n', { flag: 'a' }, (err) => {
  if (err) throw err;
  console.log('Лог добавлен!');
});

Таблица популярных флагов

Флаг Описание
'w'
Запись (создать/перезаписать)
'a'
Добавление (append)
'wx'
Запись только если файла нет
'ax'
Добавление только если файла нет

6. Как узнать, что файл записан? Обработка ошибок

Асинхронный метод всегда требует колбэк-функцию. Никогда не игнорируйте ошибку — иначе потом будете долго искать, почему файл не сохранился (или сохранился не туда).

Пример: ловим ошибку записи

fs.writeFile('/root/protected.txt', 'Тест', (err) => {
  if (err) {
    // Например, нет прав на запись
    console.error('Ошибка:', err.message);
  } else {
    console.log('Файл записан!');
  }
});

Пример: try/catch для синхронного метода

try {
  fs.writeFileSync('/root/protected.txt', 'Тест');
} catch (err) {
  console.error('Ошибка при синхронной записи:', err.message);
}

7. Полезные нюансы

Работа с объектами: запись JSON

В реальных приложениях часто нужно сохранять не просто текст, а структуру данных. Для этого используют сериализацию в JSON.

Пример: сохраняем объект пользователя

const user = {
  name: 'Иван',
  age: 30,
  email: 'ivan@example.com'
};

fs.writeFile('user.json', JSON.stringify(user, null, 2), (err) => {
  if (err) throw err;
  console.log('Пользователь сохранён в user.json!');
});

JSON.stringify(obj, null, 2) делает красивый отступ (2 пробела) для читаемости.

Перезапись файла

fs.writeFile и fs.writeFileSync по умолчанию полностью затирают старое содержимое файла. Если вы хотите сохранить старые данные, используйте fs.appendFile или опцию { flag: 'a' }.

Размер файла

Нет ограничений на размер данных, но для больших файлов лучше использовать потоки (fs.createWriteStream) — об этом будет отдельная лекция.

Запись бинарных данных

Можно писать не только строки, но и Buffer'ы (например, картинки):

const imageBuffer = ...; // получили из другого источника
fs.writeFile('image.png', imageBuffer, (err) => {
  if (err) throw err;
  console.log('Картинка сохранена!');
});

8. Типичные ошибки при работе с записью файлов

Очень часто новички забывают проверить, что вернулось в err в колбэке или не оборачивают синхронную запись в try/catch. В результате ошибки записи остаются незамеченными, а данные теряются.

Если вы хотите добавить данные в файл, но используете fs.writeFile без флага 'a' или fs.appendFile, старое содержимое будет уничтожено. Не забывайте про флаги!

Вызов fs.writeFileSync в обработчике HTTP-запроса может «заморозить» сервер для всех пользователей, пока файл пишется. Используйте синхронные методы только там, где это действительно оправдано.

Забыли сериализовать объект в JSON? В результате в файле окажется [object Object] вместо ожидаемой структуры. Используйте JSON.stringify для объектов.

Если записываете не-UTF8 текст, обязательно указывайте нужную кодировку. Иначе потом будете видеть кракозябры вместо кириллицы.

Если путь к файлу включает несуществующую папку, запись завершится ошибкой. Проверьте, что все папки существуют, или создайте их заранее (fs.mkdir).

1
Задача
Модуль 4: Node.js, Next.js и Angular, 3 уровень, 2 лекция
Недоступна
Асинхронная запись объекта в формате JSON
Асинхронная запись объекта в формате JSON
1
Задача
Модуль 4: Node.js, Next.js и Angular, 3 уровень, 2 лекция
Недоступна
Запись и добавление данных с помощью разных опций
Запись и добавление данных с помощью разных опций
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ