JS Tower
Node.jsМодуль 3: Файловая система

Модуль fs

Чтение, запись и удаление файлов

Цель урока

В этом уроке ты научишься:

  • Читать файлы синхронно и асинхронно
  • Записывать данные в файлы
  • Удалять и переименовывать файлы

Импорт модуля

// Callback API
const fs = require('fs');

// Promise API (рекомендуется)
const fs = require('fs/promises');

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

Асинхронное (Promise)

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

async function readFile() {
  try {
    const data = await fs.readFile('file.txt', 'utf8');
    console.log(data);
  } catch (error) {
    console.error('Ошибка чтения:', error.message);
  }
}

readFile();

Асинхронное (Callback)

const fs = require('fs');

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('Ошибка:', err.message);
    return;
  }
  console.log(data);
});

Синхронное

const fs = require('fs');

try {
  const data = fs.readFileSync('file.txt', 'utf8');
  console.log(data);
} catch (error) {
  console.error('Ошибка:', error.message);
}

Внимание

Синхронные методы блокируют Event Loop. Используй их только при запуске приложения.


Запись файлов

Перезапись

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

async function writeFile() {
  await fs.writeFile('output.txt', 'Привет, мир!', 'utf8');
  console.log('Файл записан');
}

Добавление в конец

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

async function appendFile() {
  await fs.appendFile('log.txt', 'Новая строка\n', 'utf8');
  console.log('Строка добавлена');
}

С опциями

await fs.writeFile('file.txt', data, {
  encoding: 'utf8',
  mode: 0o644,  // Права доступа
  flag: 'w'    // w - перезапись, a - добавление
});

Удаление файлов

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

// Удаление файла
await fs.unlink('file.txt');

// Удаление с проверкой существования
async function deleteFile(path) {
  try {
    await fs.unlink(path);
    console.log('Файл удален');
  } catch (error) {
    if (error.code === 'ENOENT') {
      console.log('Файл не существует');
    } else {
      throw error;
    }
  }
}

Переименование и перемещение

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

// Переименование
await fs.rename('old.txt', 'new.txt');

// Перемещение
await fs.rename('file.txt', 'folder/file.txt');

Копирование

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

// Node.js 16.7+
await fs.copyFile('source.txt', 'destination.txt');

// С флагами
await fs.copyFile('source.txt', 'dest.txt', fs.constants.COPYFILE_EXCL);
// COPYFILE_EXCL - ошибка если dest существует

Информация о файле

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

const stats = await fs.stat('file.txt');

console.log('Размер:', stats.size, 'байт');
console.log('Это файл:', stats.isFile());
console.log('Это директория:', stats.isDirectory());
console.log('Создан:', stats.birthtime);
console.log('Изменен:', stats.mtime);

Проверка существования

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

async function exists(path) {
  try {
    await fs.access(path);
    return true;
  } catch {
    return false;
  }
}

if (await exists('file.txt')) {
  console.log('Файл существует');
}

Права доступа

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

// Изменение прав
await fs.chmod('file.txt', 0o755);

// Проверка доступа
try {
  await fs.access('file.txt', fs.constants.R_OK | fs.constants.W_OK);
  console.log('Файл доступен для чтения и записи');
} catch {
  console.log('Нет доступа');
}

Практика

Задание 1: Чтение и запись

Задача: Прочитай файл и запиши его содержимое в верхнем регистре.

Решение:

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

async function upperCase(input, output) {
  const data = await fs.readFile(input, 'utf8');
  await fs.writeFile(output, data.toUpperCase(), 'utf8');
}

upperCase('input.txt', 'output.txt');

Задание 2: Логгер

Задача: Создай функцию для записи логов с датой.

Решение:

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

async function log(message) {
  const timestamp = new Date().toISOString();
  const entry = `[${timestamp}] ${message}\n`;
  await fs.appendFile('app.log', entry, 'utf8');
}

await log('Приложение запущено');
await log('Пользователь авторизован');

Проверь себя

  1. Чем writeFile отличается от appendFile?
  2. Когда использовать синхронные методы?
  3. Как проверить существование файла?