Работа с файловой системой в JavaScript: практическое руководство для Node.js

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Зачем уметь работать с файлами в JavaScript?

Когда мы говорим о JavaScript, большинство сразу вспоминает браузер и интерактивные интерфейсы. Однако с появлением платформы Node.js JavaScript вышел далеко за пределы веб-страниц. Сегодня это полноценный язык для серверной разработки, автоматизации и утилит. И одна из ключевых задач, с которой сталкивается каждый разработчик — это работа с файловой системой.

Умение читать, записывать, перемещать и удалять файлы — это база, без которой невозможно представить ни один серьёзный проект. Будь то логгер, конфигурационный файл, загрузка изображений или анализ данных — везде нужен доступ к файловой системе.

В этой статье мы разберём практические примеры работы с файловой системой в Node.js. Вы узнаете, как использовать встроенный модуль fs, какие существуют методы и как избежать типичных ошибок. Весь код можно сразу запускать и тестировать.

Основные методы модуля fs

Модуль fs (File System) входит в стандартную поставку Node.js. Его не нужно устанавливать отдельно. Для начала работы достаточно подключить его в начале файла:

const fs = require('fs');
const fsPromises = require('fs').promises; // для работы с промисами

Все методы модуля fs существуют в трёх вариантах:

  • Синхронные — блокируют выполнение кода до завершения операции. Обычно имеют суффикс Sync.
  • Асинхронные с колбэками — классический стиль Node.js.
  • Асинхронные на промисах — современный подход через fs.promises.

В современных проектах рекомендуется использовать промисы и async/await. Это делает код чище и понятнее.

Чтение файлов

Самый частый сценарий — прочитать содержимое файла. Рассмотрим пример с текстовым файлом data.txt:

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

async function readFileExample() {
    try {
        const data = await fs.readFile('data.txt', 'utf8');
        console.log('Содержимое файла:');
        console.log(data);
    } catch (err) {
        console.error('Ошибка чтения файла:', err.message);
    }
}

readFileExample();

Второй параметр 'utf8' указывает кодировку. Если его опустить, вы получите сырой буфер (Buffer). Для текстовых файлов всегда указывайте кодировку.

Запись в файл

Запись данных в файл может выполняться двумя способами: полная перезапись или добавление в конец.

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

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

async function writeFileExample() {
    try {
        await fs.writeFile('output.txt', 'Привет, файловая система!');
        console.log('Файл успешно записан');
    } catch (err) {
        console.error('Ошибка записи:', err.message);
    }
}

writeFileExample();

Добавление в конец файла:

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

async function appendFileExample() {
    try {
        await fs.appendFile('log.txt', `Новая запись: ${new Date().toISOString()}\n`);
        console.log('Данные добавлены');
    } catch (err) {
        console.error('Ошибка добавления:', err.message);
    }
}

appendFileExample();

Метод appendFile идеально подходит для ведения логов или накопления данных.

Управление директориями и файлами

Работа с файловой системой не ограничивается чтением и записью. Часто требуется создавать папки, проверять существование файлов или удалять их.

Создание и удаление директорий

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

async function manageDirectories() {
    try {
        // Создание директории (если её нет)
        await fs.mkdir('myFolder', { recursive: true });
        console.log('Папка создана');

        // Удаление пустой директории
        await fs.rmdir('myFolder');
        console.log('Папка удалена');
    } catch (err) {
        console.error('Ошибка:', err.message);
    }
}

manageDirectories();

Опция { recursive: true } позволяет создавать вложенные папки, например ./a/b/c, не беспокоясь о том, что родительские папки не существуют.

Проверка существования файла или папки

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

async function checkExists() {
    try {
        await fs.access('myFile.txt');
        console.log('Файл существует');
    } catch {
        console.log('Файл не найден');
    }
}

checkExists();

Метод access не возвращает содержимого, а только проверяет доступность пути. Это быстрый способ узнать, существует ли файл или папка.

Копирование и перемещение файлов

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

async function copyAndMove() {
    try {
        // Копирование
        await fs.copyFile('source.txt', 'destination.txt');
        console.log('Файл скопирован');

        // Переименование (перемещение)
        await fs.rename('oldName.txt', 'newName.txt');
        console.log('Файл переименован');
    } catch (err) {
        console.error('Ошибка:', err.message);
    }
}

copyAndMove();

Метод rename работает и как перемещение между папками: fs.rename('./folder/file.txt', './other/file.txt').

Практический пример: утилита для логирования

Давайте соберём всё вместе и создадим простую, но полезную утилиту для записи логов с автоматической ротацией по дням.

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

class Logger {
    constructor(logDir = 'logs') {
        this.logDir = logDir;
    }

    async init() {
        await fs.mkdir(this.logDir, { recursive: true });
    }

    getLogFileName() {
        const today = new Date().toISOString().slice(0, 10); // '2025-04-08'
        return path.join(this.logDir, `log-${today}.txt`);
    }

    async log(level, message) {
        const timestamp = new Date().toISOString();
        const logLine = `[${timestamp}] [${level.toUpperCase()}] ${message}\n`;

        try {
            await fs.appendFile(this.getLogFileName                

Блоги

Рекомендаций по книгам