Пошук уроків, статей та іншого контенту
Ознайомтеся з модулем fs та основними методами Node.js для взаємодії з файловою системою.
fsfs — вбудований модуль Node.js для роботи з файловою системою. За його допомогою можна:
читати та записувати файли;
додавати дані до файлів;
створювати й видаляти файли та каталоги;
отримувати інформацію про файли;
переглядати вміст каталогів.
Модулі Node.js не потрібно встановлювати через npm. Модуль fs доступний одразу після встановлення Node.js.
Є два основні способи використання fs:
асинхронний — не блокує виконання програми;
синхронний — призупиняє виконання програми до завершення операції.
Для більшості прикладних програм варто використовувати асинхронні методи.
Сучасний варіант для асинхронної роботи — імпортувати fs/promises:
const fs = require("fs/promises");Методи цього модуля повертають проміси, тому їх зручно використовувати з async і await.
Також можна підключити звичайний модуль fs:
const fs = require("fs");Він містить асинхронні методи з callback-функціями та синхронні методи.
Для читання файлу використовується метод readFile.
Нехай у поточному каталозі є файл message.txt:
Привіт із файлу!Прочитати його можна так:
const fs = require("fs/promises");
async function readMessage() {
const content = await fs.readFile("message.txt", "utf8");
console.log(content);
}
readMessage().catch((error) => {
console.error("Не вдалося прочитати файл:", error.message);
});Другий аргумент "utf8" вказує, що результат потрібно повернути як текст.
Без кодування readFile повертає об’єкт Buffer — набір байтів:
const fs = require("fs/promises");
async function readFileAsBuffer() {
const content = await fs.readFile("message.txt");
console.log(content);
}
readFileAsBuffer();Для текстових файлів зазвичай потрібно явно вказувати "utf8".
Метод writeFile створює файл або повністю замінює його вміст, якщо файл уже існує:
const fs = require("fs/promises");
async function saveMessage() {
await fs.writeFile("message.txt", "Новий текст у файлі", "utf8");
console.log("Файл збережено");
}
saveMessage().catch((error) => {
console.error("Не вдалося записати файл:", error.message);
});Якщо файл message.txt не існує, Node.js створить його.
Якщо файл уже містить текст, старий вміст буде видалено та замінено новим.
Щоб не замінювати наявний вміст, використовуйте appendFile:
const fs = require("fs/promises");
async function addLogEntry() {
await fs.appendFile("log.txt", "Нова подія\n", "utf8");
console.log("Запис додано");
}
addLogEntry().catch((error) => {
console.error("Не вдалося додати запис:", error.message);
});Кожен виклик appendFile додає текст у кінець файлу.
Метод зручно використовувати для простих журналів подій:
await fs.appendFile("log.txt", `${new Date().toISOString()} — запуск програми\n`);Для створення каталогу використовується mkdir:
const fs = require("fs/promises");
async function createDirectory() {
await fs.mkdir("data");
console.log("Каталог створено");
}
createDirectory().catch((error) => {
console.error("Не вдалося створити каталог:", error.message);
});Якщо каталог уже існує, цей код завершиться помилкою. Щоб не отримувати помилку в такому випадку, передайте параметр recursive: true:
const fs = require("fs/promises");
async function createDirectory() {
await fs.mkdir("data/files", { recursive: true });
console.log("Каталоги створено");
}
createDirectory();Параметр recursive: true створює всі відсутні каталоги у вказаному шляху.
У назві файлу можна вказувати шлях до каталогу:
const fs = require("fs/promises");
async function workWithDataFile() {
await fs.mkdir("data", { recursive: true });
await fs.writeFile(
"data/user.txt",
"Ім'я: Олена\nМісто: Львів",
"utf8"
);
const content = await fs.readFile("data/user.txt", "utf8");
console.log(content);
}
workWithDataFile().catch((error) => {
console.error("Помилка:", error.message);
});У великих програмах шлях краще формувати за допомогою модуля path. Це допомагає коректно працювати на різних операційних системах:
const path = require("path");
const filePath = path.join("data", "user.txt");
console.log(filePath);У Windows і Unix-подібних системах роздільники шляхів можуть відрізнятися, а path.join враховує це автоматично.
Метод readdir повертає список файлів і підкаталогів:
const fs = require("fs/promises");
async function showDirectoryContents() {
const files = await fs.readdir(".");
console.log(files);
}
showDirectoryContents().catch((error) => {
console.error("Не вдалося прочитати каталог:", error.message);
});Точка "." означає поточний каталог.
Щоб отримати більше інформації про кожен елемент, можна використати параметр withFileTypes:
const fs = require("fs/promises");
async function showEntries() {
const entries = await fs.readdir(".", { withFileTypes: true });
for (const entry of entries) {
const type = entry.isDirectory() ? "каталог" : "файл";
console.log(`${entry.name} — ${type}`);
}
}
showEntries().catch((error) => {
console.error("Помилка:", error.message);
});Метод isDirectory() перевіряє, чи є елемент каталогом.
Метод stat повертає інформацію про файл або каталог:
const fs = require("fs/promises");
async function showFileInfo() {
const stats = await fs.stat("message.txt");
console.log("Це файл:", stats.isFile());
console.log("Це каталог:", stats.isDirectory());
console.log("Розмір у байтах:", stats.size);
console.log("Дата зміни:", stats.mtime);
}
showFileInfo().catch((error) => {
console.error("Не вдалося отримати інформацію:", error.message);
});Корисні властивості та методи об’єкта stats:
size — розмір у байтах;
mtime — дата останньої зміни;
isFile() — перевірка, чи є об’єкт файлом;
isDirectory() — перевірка, чи є об’єкт каталогом.
Для перейменування або переміщення файлу використовується rename:
const fs = require("fs/promises");
async function renameFile() {
await fs.rename("old-name.txt", "new-name.txt");
console.log("Файл перейменовано");
}
renameFile().catch((error) => {
console.error("Не вдалося перейменувати файл:", error.message);
});Для видалення файлу використовується unlink:
const fs = require("fs/promises");
async function deleteFile() {
await fs.unlink("new-name.txt");
console.log("Файл видалено");
}
deleteFile().catch((error) => {
console.error("Не вдалося видалити файл:", error.message);
});Для видалення каталогу можна використати rm:
const fs = require("fs/promises");
async function deleteDirectory() {
await fs.rm("data", { recursive: true, force: true });
console.log("Каталог видалено");
}
deleteDirectory().catch((error) => {
console.error("Не вдалося видалити каталог:", error.message);
});Параметр recursive: true дозволяє видалити каталог разом із його вмістом. Параметр force: true не спричиняє помилку, якщо каталог не існує.
Синхронні методи мають суфікс Sync:
const fs = require("fs");
try {
fs.writeFileSync("sync-message.txt", "Текст синхронного файлу", "utf8");
const content = fs.readFileSync("sync-message.txt", "utf8");
console.log(content);
} catch (error) {
console.error("Помилка роботи з файлом:", error.message);
}Синхронний виклик блокує виконання програми:
const content = fs.readFileSync("message.txt", "utf8");
console.log("Цей рядок виконається після завершення читання");Асинхронний варіант не блокує потік Node.js:
const fs = require("fs/promises");
async function readFileAsync() {
const content = await fs.readFile("message.txt", "utf8");
console.log(content);
}
readFileAsync();
console.log("Цей рядок може виконатися до завершення читання файлу");Синхронні методи можуть бути доречними для невеликих одноразових операцій, наприклад під час запуску конфігурації. Для серверних обробників і регулярних операцій зазвичай використовують асинхронні методи.
Наступна програма:
створює каталог notes;
записує файл;
додає до нього рядок;
читає файл;
показує список елементів каталогу;
виводить інформацію про файл.
const fs = require("fs/promises");
const path = require("path");
async function main() {
const directoryPath = path.join(process.cwd(), "notes");
const filePath = path.join(directoryPath, "today.txt");
// Створюємо каталог, якщо його ще немає
await fs.mkdir(directoryPath, { recursive: true });
// Записуємо початковий текст у файл
await fs.writeFile(filePath, "План на сьогодні:\n", "utf8");
// Додаємо нові рядки
await fs.appendFile(filePath, "- Вивчити модуль fs\n", "utf8");
await fs.appendFile(filePath, "- Написати практичний приклад\n", "utf8");
// Читаємо весь файл
const content = await fs.readFile(filePath, "utf8");
console.log("Вміст файлу:");
console.log(content);
// Отримуємо список елементів у каталозі
const entries = await fs.readdir(directoryPath);
console.log("Елементи каталогу:");
console.log(entries);
// Отримуємо інформацію про файл
const stats = await fs.stat(filePath);
console.log("Розмір файлу:", stats.size, "байт");
console.log("Остання зміна:", stats.mtime);
}
main().catch((error) => {
console.error("Сталася помилка:", error.message);
});Збережіть код у файлі fs-demo.js і запустіть командою:
node fs-demo.jsПісля запуску поруч зі скриптом з’явиться каталог notes із файлом today.txt.
Операції з файловою системою можуть завершитися помилкою. Наприклад:
файл не існує;
немає дозволу на читання або запис;
каталог у вказаному шляху відсутній;
програма намагається створити елемент, який уже існує.
Проміси з fs/promises обробляють за допомогою try...catch:
const fs = require("fs/promises");
async function readOptionalFile() {
try {
const content = await fs.readFile("optional.txt", "utf8");
console.log(content);
} catch (error) {
if (error.code === "ENOENT") {
console.log("Файл не знайдено");
} else {
console.error("Невідома помилка:", error.message);
}
}
}
readOptionalFile();Властивість error.code містить код системної помилки. Наприклад, ENOENT означає, що файл або каталог не знайдено.
Якщо прочитати текстовий файл без "utf8", результатом буде Buffer:
const content = await fs.readFile("message.txt");Для отримання рядка використовуйте:
const content = await fs.readFile("message.txt", "utf8");writeFile замінює наявний вміст файлу:
await fs.writeFile("log.txt", "Нова подія");Якщо потрібно додати текст, використовуйте appendFile:
await fs.appendFile("log.txt", "Ще одна подія\n");Асинхронні операції потрібно очікувати за допомогою await:
await fs.writeFile("message.txt", "Текст", "utf8");
const content = await fs.readFile("message.txt", "utf8");Якщо не використати await, читання може розпочатися раніше, ніж завершиться запис.
Запис у файл усередині неіснуючого каталогу завершиться помилкою:
await fs.writeFile("data/message.txt", "Текст", "utf8");Спочатку створіть каталог:
await fs.mkdir("data", { recursive: true });
await fs.writeFile("data/message.txt", "Текст", "utf8");Відносний шлях на кшталт "data/file.txt" обчислюється від поточного робочого каталогу програми. Перевірити його можна так:
console.log(process.cwd());Для складання шляхів використовуйте path.join, а не ручне поєднання рядків.
fs — вбудований модуль Node.js для роботи з файловою системою.
fs/promises містить асинхронні методи, які зручно використовувати з async/await.
readFile читає файл.
writeFile створює файл або замінює його вміст.
appendFile додає дані в кінець файлу.
mkdir створює каталог.
readdir повертає вміст каталогу.
stat надає інформацію про файл або каталог.
rename перейменовує або переміщує файл.
unlink видаляє файл.
Для обробки помилок використовуйте try...catch.
Під час роботи з текстом зазвичай потрібно вказувати кодування "utf8".
Для формування шляхів зручно використовувати модуль path.