fs.writeFile(path, data, callback) записывает строку или Buffer в файл. Если файла нет, Node его создаёт; если есть, старое содержимое заменяется. fs.writeFileSync(path, data) делает то же самое и ждёт окончания записи, а fs.appendFile дописывает в конец файла, а не заменяет его.
Программа выводит saved, а затем текст, прочитанный обратно; callback получает только ошибку (или null), но никогда не данные. Передайте 42 вместо строки, и вызов выбросит TypeError: данные должны быть строкой или Buffer.
writeFile, writeFileSync и fs/promises
Три формы принимают одинаковые аргументы и отличаются тем, как вы ждёте результат.
const fs = require('fs');
const fsp = require('fs/promises');
fs.writeFileSync('a.txt', 'one'); // blocks, throws on error
fs.writeFile('b.txt', 'two', (err) => {}); // callback with err
await fsp.writeFile('c.txt', 'three'); // promise, use in async code
Используйте writeFileSync в скриптах и коде запуска, а версию на промисах на серверах, где синхронная запись блокирует все остальные запросы, пока диск не закончит. Остальной API на промисах показан на странице про fs/promises.
Дописать в файл через appendFile
writeFile заменяет файл целиком. Чтобы добавить строку в лог, используйте appendFile, который в первый раз тоже создаёт файл.
Первое чтение выводит "second\n", потому что второй writeFileSync заменил first, а второе выводит "second\nthird\nfourth\n" (JSON.stringify делает переводы строк видимыми). Добавляйте \n сами: ни одна из функций его не добавляет.
writeFile | appendFile | |
|---|---|---|
| Файла нет | Создаёт его | Создаёт его |
| Файл есть | Заменяет содержимое | Дописывает в конец |
| Флаг по умолчанию | 'w' | 'a' |
| Для чего обычно | Сохранить документ или JSON целиком | Логи, по одной строке |
Не перезаписывать: опция flag
Третьим аргументом можно передать объект опций. Его flag решает, что будет с существующим файлом. 'wx' значит «записать, но упасть, если файл уже есть», и это безопасный способ создать файл только один раз.
Второй вызов падает с EEXIST, поэтому в файле по-прежнему abc123. Поменяйте имя файла во втором вызове на id2.txt, и оба вызова выведут created.
Флаги, которые встречаются чаще всего: 'w' (по умолчанию, заменить), 'a' (дописать), 'wx' (только создать) и 'ax' (дописать, но только в новый файл).
Если сначала проверить через fs.existsSync, а потом записать, остаётся щель: другой процесс может создать файл между проверкой и записью. 'wx' делает и то и другое за один шаг.
Запись JSON в файл
writeFile не принимает объекты. Превратите их в текст через JSON.stringify; третий аргумент, 2, добавляет отступы, чтобы файл было удобно читать.
В файле объект записан на нескольких строках с отступами, а после разбора получается такой же объект, поэтому последняя строка выводит 2. Передайте объект без JSON.stringify, и вызов выбросит TypeError.
Сначала создайте папку через mkdir
writeFile создаёт файлы, но не папки. Запись в reports/2026/june.txt, когда папки reports нет, падает с ENOENT. Сначала создайте путь через mkdir с { recursive: true }: он создаёт все недостающие папки и ничего не делает, если они уже есть.
Первая запись падает с ENOENT; после mkdir та же запись проходит, и readdir показывает [ 'june.txt' ]. В настоящем коде собирайте такие пути через path.join, чтобы они работали и в Windows.
Частые ошибки
Ожидание, что файл записан сразу после вызова. fs.writeFile возвращается раньше, чем данные окажутся на диске. Читайте файл или переходите к следующему шагу внутри callback'а или дождитесь версии на промисах через await.
Потеря данных при записи в цикле. Вызов writeFile для каждого элемента каждый раз заменяет файл, и в нём остаётся только последний элемент. Используйте appendFile или соберите всю строку и запишите её один раз.
Запись [object Object]. Если пропустить объект через String() или шаблонную строку, запишется [object Object]. Используйте JSON.stringify.
Часто задаваемые вопросы
fs.writeFile перезаписывает файл?
Да. С флагом по умолчанию 'w' он обрезает файл и записывает новые данные, так что старое содержимое пропадает. Чтобы дописать в конец, передайте { flag: 'a' } или используйте appendFile.
fs.writeFile создаёт файл, если его нет?
Да, файл он создаёт. А вот недостающие папки нет: запись в logs/app.log, когда папки logs нет, падает с ENOENT.
Что можно передать как данные?
Строку, Buffer или типизированный массив. Всё остальное, например объект или число, выбрасывает TypeError, поэтому сначала преобразуйте объекты через JSON.stringify, а числа через String().
Можно ли вызывать writeFile много раз одновременно для одного файла?
Нет. Два параллельных вызова writeFile для одного файла могут перемешаться и оставить смешанное содержимое. Дождитесь окончания одного, прежде чем начинать следующий, или соберите данные и запишите один раз.