4. Файловая система (fs, path)

Модуль fs даёт полный доступ к файловой системе: чтение, запись, удаление, создание папок.
Чтение файлов
Заголовок раздела «Чтение файлов»const { readFile, readFileSync } = require('fs');const { readFile: readFileAsync } = require('fs/promises');
// ✅ Async/await (рекомендуется)async function readConfig() { try { const content = await readFileAsync('./config.json', 'utf8'); return JSON.parse(content); } catch (err) { console.error('Ошибка чтения:', err.message); return null; }}
// Callback стильreadFile('./data.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data);});
// Синхронный (блокирует Event Loop — только для запуска приложения)const data = readFileSync('./config.json', 'utf8');const config = JSON.parse(data);Запись файлов
Заголовок раздела «Запись файлов»const { writeFile, appendFile } = require('fs/promises');
// Перезапись файлаawait writeFile('./output.txt', 'Привет, файл!', 'utf8');
// Запись JSONconst users = [{ id: 1, name: 'Яша' }, { id: 2, name: 'Лёха' }];await writeFile('./users.json', JSON.stringify(users, null, 2), 'utf8');
// Добавление в конец файлаawait appendFile('./log.txt', `${new Date().toISOString()} — событие\n`);
// Запись бинарных данных (Buffer)const buffer = Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]);await writeFile('./binary.bin', buffer);Работа с директориями
Заголовок раздела «Работа с директориями»const { mkdir, readdir, rmdir, rm } = require('fs/promises');
// Создание директорииawait mkdir('./uploads', { recursive: true }); // recursive — создаёт вложенные папки
// Список файлов в папкеconst files = await readdir('./src');console.log(files); // ['index.js', 'utils.js', ...]
// С информацией о файлахconst entries = await readdir('./src', { withFileTypes: true });for (const entry of entries) { if (entry.isDirectory()) { console.log(`📁 ${entry.name}/`); } else { console.log(`📄 ${entry.name}`); }}
// Удаление директории с содержимым (Node.js 14.14+)await rm('./temp', { recursive: true, force: true });Информация о файле
Заголовок раздела «Информация о файле»const { stat, access } = require('fs/promises');const { constants } = require('fs');
// Статистика файлаconst info = await stat('./data.json');console.log(info.size); // размер в байтахconsole.log(info.isFile()); // true/falseconsole.log(info.isDirectory()); // true/falseconsole.log(info.mtime); // дата измененияconsole.log(info.birthtime); // дата создания
// Проверка существования файлаasync function fileExists(path) { try { await access(path, constants.F_OK); return true; } catch { return false; }}
const exists = await fileExists('./config.json');if (!exists) { console.log('Файл не найден, создаём по умолчанию...');}Наблюдение за файлами (watch)
Заголовок раздела «Наблюдение за файлами (watch)»const { watch } = require('fs');
// Следить за изменениями файлаconst watcher = watch('./config.json', (eventType, filename) => { console.log(`Событие: ${eventType}, файл: ${filename}`); // eventType: 'change' или 'rename'});
// Следить за директориейwatch('./src', { recursive: true }, (eventType, filename) => { console.log(`${eventType}: ${filename}`);});
// Остановить слежениеwatcher.close();path — работа с путями
Заголовок раздела «path — работа с путями»const path = require('path');
// Основные методыpath.join('/home', 'user', 'file.txt') // /home/user/file.txtpath.resolve('src', 'index.js') // /cwd/src/index.jspath.basename('/home/user/file.txt') // file.txtpath.dirname('/home/user/file.txt') // /home/userpath.extname('photo.jpg') // .jpgpath.parse('/home/user/file.txt')// { root: '/', dir: '/home/user', base: 'file.txt', ext: '.txt', name: 'file' }
// Проверка абсолютности путиpath.isAbsolute('/home/user') // truepath.isAbsolute('./src') // false
// Нормализация путиpath.normalize('/home/user/../user/./file') // /home/user/fileПрактический пример: менеджер файлов
Заголовок раздела «Практический пример: менеджер файлов»const { readFile, writeFile, readdir, mkdir, stat } = require('fs/promises');const path = require('path');
class FileManager { constructor(baseDir) { this.baseDir = baseDir; }
// Полный путь resolve(...parts) { return path.join(this.baseDir, ...parts); }
// Читать JSON файл async readJSON(filename) { const content = await readFile(this.resolve(filename), 'utf8'); return JSON.parse(content); }
// Записать JSON файл async writeJSON(filename, data) { await writeFile( this.resolve(filename), JSON.stringify(data, null, 2), 'utf8' ); }
// Список всех файлов async listFiles(subdir = '') { const dir = this.resolve(subdir); const entries = await readdir(dir, { withFileTypes: true }); return entries.map(e => ({ name: e.name, type: e.isDirectory() ? 'dir' : 'file', })); }
// Создать папку async ensureDir(subdir) { await mkdir(this.resolve(subdir), { recursive: true }); }}
// Использованиеconst fm = new FileManager('./data');await fm.ensureDir('uploads');await fm.writeJSON('users.json', [{ id: 1, name: 'Яша' }]);const users = await fm.readJSON('users.json');console.log(users);Потоки для больших файлов
Заголовок раздела «Потоки для больших файлов»const { createReadStream, createWriteStream } = require('fs');const { pipeline } = require('stream/promises');const { createGzip } = require('zlib');
// Копирование большого файла через поток (без загрузки в память)async function copyFile(src, dest) { const readable = createReadStream(src); const writable = createWriteStream(dest); await pipeline(readable, writable); console.log('Скопировано!');}
// Сжатие файла gzipasync function compressFile(src, dest) { const readable = createReadStream(src); const gzip = createGzip(); const writable = createWriteStream(dest); await pipeline(readable, gzip, writable); console.log('Сжато!');}Практика
Заголовок раздела «Практика»- Создай функцию
readJSON(path)— читает JSON файл и возвращает объект - Создай функцию
saveLog(message)— добавляет строку с датой вlogs/app.log - Напиши скрипт, который рекурсивно обходит папку и выводит все
.jsфайлы - Создай простой конфиг-менеджер:
getConfig(),setConfig(key, value),resetConfig() - Реализуй функцию
copyDir(src, dest)— копирует директорию со всем содержимым