Робота з файлами
Модуль FileSystem
Модуль FileSystem відповідає за роботу з файлами в Node.js.
const fs = require('fs');
Сучасна ініціалізація модуля з промісами відбувається наступним чином:
const fs = require('fs').promises;
Методи, які найбільше використовують для основних операцій з файлами:
fs.readFile(filename, [options]) - читання файлу
fs.writeFile(filename, data, [options]) - запис файлу
fs.appendFile(filename, data, [options])- додавання у файл
fs.rename(oldPath, newPath) - перейменування файлу
fs.unlink(path, callback) - видалення файлу
Синхронна робота з файлами
Методи бувають синхронні і асинхронні (про це вказує його назва - закінчується на Sync). Краще вживати без Sync у назві, бо якщо буде великий файл для читання, то дія заблокується поки не обробиться процес читання.
fs.readFileSync();
fs.readFile();
Потрібно підключати так:
const fs = require('fs');
Але в такому разі всі підключені функції не повертають проміс і їм необхідний callback. Синхронним функціям callback не потрібен, бо вони є блокувальними і тому вони не рекомендовані до застосування, тільки якщо це вимагає поточне завдання, і ви чітко розумієте навіщо ви їх використовуєте.
JS-доки
/**
* read and write operations
*/
Також можна вказувати яке значення повертатиме функція.
/**
* read and write operations
* @returns {Promice<void>}
*/
void - в даному випадку означає null або undefined. Можна вказати, що функція повертатиме number або string тощо.
Читання файлу. Buffer
При роботі з файлами всі функції мають бути асинхронні. Бо ми не можемо знати наперед коли буде результат опрацювання команди. Те ж саме стосується роботи з мережею або запитом на REST API.
Також не забуваємо обробляти помилки. Використовуємо синтаксис .then().catch(); або async/await в поєднанні з try{} catch(){}
Створимо невеликий текстовий файл readme.txt, в якому запишемо якусь невелику фразу. Тоді функція читання цього файлу виглядатиме так:
fs.readFile('readme.txt')
.then(data => console.log(data))
.catch(err => console.log(err.message));
або ось так
const fs = require('fs').promises;
const readMyFile = async () => {
try {
const data = await fs.readFile('readme.txt');
console.log(data);
} catch (err) {
console.log(err);
}
};
readMyFile();
Параметр data у функції readFile, містить об'єкт типу Buffer. Це - послідовність прочитаних байтів (тобто сирі дані).
Отримання валідних даних при читанні
Найпростіший спосіб працювати з отриманими даними як з рядком - необхідно конвертувати data методом toString().
fs.readFile('readme.txt')
.then(data => console.log(data.toString()))
.catch(err => console.log(err.message));
або ось так
const fs = require('fs').promises;
const readMyFile = async () => {
try {
const data = await fs.readFile('readme.txt');
const txt = data.toString();
console.log(txt);
} catch (err) {
console.log(err);
}
};
readMyFile();
Після такої операції ми вже отримаємо не бінарний код, а зрозумілий рядковий формат даних.
Опрацювання шляхів до файлу
Припустимо, що файл, який потрібно зчитати зберігається у папці documents, яка своєю чергою лежить у папці files.
myProject
├── index.js
└── files
└── documents
└── readme.txt
В такому разі нам доведеться прописати повний шлях до файлу.
const data = await fs.readFile('files/documents/readme.txt');
Утім тут є складність в тому, що операційні системи macOS та Unix проставляють в шляхах такий слеш /, а в операційній системі windows такий \. Тому код шляху, який працюватиме в одні ос, не працюватиме в іншій. Для вирішення цього ньюансу є модуль path.
Підключення:
const path = require("path");
В такому разі ми просто через кому передаємо кожен рівень шляху до файлу, а цей модуль path поставить правильні слеші за нас.
const fs = require('fs').promises;
const path = require("path");
const readMyFile = async () => {
try {
const pathToFile = path.join("files", "documents", "readme.txt");
const data = await fs.readFile(pathToFile);
const txt = data.toString();
console.log(txt);
} catch (err) {
console.log(err);
}
};
readMyFile();
Читання/запис JSON-файлу
Припустімо, що маємо таку структуру проєкту
myProject
├── index.js
└── files
└── sample.json
{
"a": 123,
"b": "Mike",
"c": true,
"d": "Helen"
}
Зчитаймо вміст sample.json, внесемо зміни та збережемо у новий файл newJson.json на рівні з index.js.
const fs = require("fs").promises;
const path = require("path");
const readWriteJson = async () => {
try {
const pathToJson = path.join("files", "sample.json");
const jsonResult = await fs.readFile(pathToJson);
console.log(jsonResult); // повернеться бафер
const json = JSON.parse(jsonResult);
console.log(json); // повернеться json
json.e = "Helga"; // внесемо зміни
// створимо новий файл
await fs.writeFile("newJson.json", JSON.stringify(json));
} catch (err) {
console.log(err);
}
};
readWriteJson();
Читання каталогу
У цьому прикладі ми будемо використовувати два методи readdir (для читання директорії) і stat (для отримання статистики).
Напишімо скрипт files.js, який читатиме поточний каталог та виводити його вміст: ім'я файлу, його розмір та дату останньої зміни.
const fs = require('fs').promises;
fs.readdir(__dirname)
.then(files => {
return Promise.all(
files.map(async filename => {
const stats = await fs.stat(filename);
return {
Name: filename,
Size: stats.size,
Date: stats.mtime,
};
}),
);
})
.then(result => console.table(result));
__dirname - повертає абсолютний шлях поточного каталогу.
У наслідку виконання промісу в змінній files міститься масив імен файлів та директорій з поточної директорії. Потім ми повертаємо масив промісів з аналізом кожного елемента цього масиву.
Провести аналіз допомагає змінна stats, де міститься інформація про поточний файл. Тут повертається ім'я файлу, час останньої зміни stats.mtime та розмір у байтах stats.size.
Результат виконання промісу, змінна result, передається функції console.table. В результаті на екран виводиться таблиця виконання скрипту в консолі.
Різновидом отримання статистики про файл є метод lstat.
fs.lstat(pathToFile);
Корисним методом також буде перевірка чи є елемент в директорії папкою чи файлом isDirectory.
console.log(dirStat.isDirectory());
Покликання:
Last updated