Файлы¶
Для работы с файлами в Node.js используется встроенный модуль fs
, который выполняет все синхронные и асинхронные операции ввода/вывода применительно к файлам. Чтение и запись файла могут осуществляться одним из двумя способов:
- с использованием
Buffer
; - через создание соответствующего потока.
Чтение файлов и директорий¶
Для чтения файла в асинхронном режиме используется метод Node.js readFile()
, который принимает три параметра:
- путь к файлу;
- кодировка;
- callback-функция, вызываемая после получения содержимого файла.
fs.readFile('files/data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
Callback-функции передается два аргумента: ошибка и полученные данные в строковом формате. Если операция прошла успешна, то в качестве ошибки передается null
.
Если в readFile()
не указать кодировку, то данные файла будут возвращены в формате Buffer
.
Поскольку метод выполняется асинхронно, то не происходит блокировки главного процесса Node.js. Но в некоторых случаях может понадобиться синхронное чтение файла, для этого есть метод readFileSync()
, но при этом выполнение главного процесса будет заблокировано до тех пор, пока полностью не будет загружено содержимое файла.
const content = fs.readFileSync('files/data.txt', 'utf8');
console.log(content);
Node.js readFileSync()
возвращает результат чтения файла и принимает два параметра:
- путь к файлу;
- кодировку.
Обработка и перехват ошибок при использовании readFileSync()
осуществляется с помощью конструкции try{...}catch(){...}
.
try {
const content = fs.readFileSync('files/data.txt', 'utf8');
console.log(content);
} catch (e) {
console.log(e);
}
Чтобы инициировать ошибку, укажите неправильный путь к файлу.
Методы readFile()
и readFileSync()
для работы с файлами используют Buffer
. Но есть и другой способ считать содержимое файла: создать поток с помощью Node.js fs.createReadStream()
. Любой поток в Node.js является экземпляром класса EventEmitter
, который позволяет обрабатывать возникающие в потоке события.
Параметры, принимаемые fs.createReadStream()
:
- путь к файлу;
- объект со следующими настройками:
encoding
- кодировка (по умолчаниюutf8
);mode
- режим доступа (по умолчанию0o666
);autoClose
- еслиtrue
, то при событияхerror
иfinish
поток закроется автоматически (по умолчаниюtrue
).
const stream = fs.createReadStream(
'files/data.txt',
'utf8'
);
stream.on('data', (data) => console.log(data));
stream.on('error', (err) => console.log(`Err: ${err}`));
Вместо объекта настроек можно передать строку, которая будет задавать кодировку.
Использование потока имеет ряд преимуществ перед Buffer
:
- Меньшее использование памяти за счет чтения содержимого по частям;
- Для объемных файлов время между запросом и ответом существенно сокращается за счет того, что данные начинают поступать по частям, а не после полной загрузки;
- Возможность перенаправить данные в другой поток с помощью метода
pipe()
.
Для чтения директорий используются методы readdir()
и readdirSync()
, для асинхронного и синхронного режимов соответственно.
Node.js readdir()
работает асинхронно и принимает три аргумента:
- путь к директории;
- кодировку;
- callback-функцию, которая принимает аргументами ошибку и массив файлов директории (при успешном выполнении операции ошибка передается как
null
).
fs.readdir('files', 'utf8', (err, files) => {
if (err) throw err;
console.log(files);
});
Node.js readdirSync()
работает синхронно, возвращает массив найденных файлов и принимает два параметра:
- путь к директории;
- кодировку.
try {
const files = fs.readdirSync('files', 'utf8');
console.log(files);
} catch (e) {
console.log(e);
}
Создание и запись файлов и директорий¶
В Node.js файлы могут быть записаны также синхронно и асинхронно. Для асинхронной записи имеется метод writeFile()
, принимающий следующие аргументы:
- путь к файлу;
- данные для записи;
- параметры записи:
- кодировка (по умолчанию
utf8
); - права доступа (по умолчанию
0o666
); - callback-функция, которая вызывается по завершению операции и единственным аргументом принимает ошибку (в случае успешной записи передается
null
).
fs.writeFile(
'files/data.txt',
'File Content',
'utf8',
(err) => {
if (err) throw err;
console.log('Done');
}
);
Если нет необходимости указывать параметры записи, то третьим параметром Node.js writeFile()
можно сразу передать callback-функцию.
Для синхронной записи Node.js файла используйте writeFileSync()
. Метод принимает все те же аргументы, что и writeFile()
за исключением callback-функции. В качестве значения возвращает undefined
.
try {
fs.writeFileSync(
'files/data.txt',
'File Content',
'utf8'
);
console.log('Done');
} catch (e) {
console.log(e);
}
Как и в случае с readFileSync()
обработка ошибок происходит с помощью try{...}catch(){...}
.
Методы writeFile()
и writeFileSync()
перезаписывают уже имеющуюся в файле информацию новыми данными. Если вам нужно внести новые данные без удаления старых, используйте методы appendFIle()
и appendFileAsync()
, которые имеют идентичные параметры.
fs.appendFile(
'files/data.txt',
'\nFile Content 2',
'utf8',
(err) => {
if (err) throw err;
console.log('Done');
}
);
Для записи файла через потока ввода имеется метод fs.createWriteStream()
, который возвращает поток ввода и принимает два параметра:
- путь к файлу;
- объект со следующими настройками:
encoding
- кодировка (по умолчаниюutf8
);mode
- режим доступа (по умолчанию0o666
);autoClose
- еслиtrue
, то при событияхerror
иfinish
поток закроется автоматически (по умолчаниюtrue
).
const stream = fs.createWriteStream(
'files/data.txt',
'utf8'
);
stream.on('error', (err) => console.log(`Err: ${err}`));
stream.on('finish', () => console.log('Done'));
stream.write('First line\n');
stream.write('Second line\n');
stream.end();
Чтобы создать директорию, используйте методы mkdir()
и mkdirSync()
.
Node.js mkdir()
работает асинхронно и принимает в качестве параметров:
- путь к директории;
- объект со следующими настройками:
recursive
- еслиtrue
, создает директорию и все ее родительские директории согласно указанному пути, если они еще не существуют (по умолчаниюfalse
, т. е. все родительские директории уже должны быть созданы, иначе будет сгенерирована ошибка);mode
- режим доступа, параметр не поддерживается на ОС Windows (по умолчанию0o777
);- callback-функцию, которая единственным аргументом принимает ошибку, при успешном создании директории передается
null
.
Вторым параметром можно сразу передать callback-функцию.
fs.mkdir('files/dir/subdir', { recursive: true }, (err) => {
if (err) throw err;
console.log('Created');
});
Node.js mkdirSync()
создает директорию синхронно и возвращает undefined
. Обработка ошибок осуществляется через try{...}catch(){...}
. Метод mkdirSync()
принимает те же параметры, что и mkdir()
, за исключением callback-функции.
try {
fs.mkdirSync('files/dir/subdir', { recursive: true });
console.log('Done');
} catch (e) {
console.log(e);
}
Удаление файлов и директорий¶
Чтобы удалить в Node.js файлы используйте методы unlink()
и unlinkSync()
.
Метод unlink()
асинхронный и принимает имя файла, который нужно удалить, и callback-функцию с ошибкой в качестве параметра (null
, если удаление прошло успешно).
fs.unlink('files/data.txt', (err) => {
if (err) throw err;
console.log('Deleted');
});
Для синхронного удаления файла используйте unlinkSync()
, которому единственным аргументом передается имя файла.
try {
fs.unlinkSync('files/data.txt');
console.log('Deleted');
} catch (e) {
console.log(e);
}
Для удаления директорий имеются методы rmdir()
и rmdirSync()
соответственно. Они полностью идентичны unlink()
и unlinkSync()
, только вместо имени файла принимают имя директории.
Пример rmdir()
.
fs.rmdir('files/dir', (err) => {
if (err) throw err;
console.log('Deleted');
});
Пример rmdirSync()
.
try {
fs.rmdirSync('files/dir');
console.log('Deleted');
} catch (e) {
console.log(e);
}
existsSync()¶
Проверка наличия в Node.js файла или директории происходит с помощью метода existsSync()
, который принимает путь к файлу или директории и возвращает либо true
, либо false
. Как вы понимаете, Node.Js existsSync()
работает в синхронном режиме.
try {
const exists = fs.existsSync('files');
console.log('Exists: ', exists);
} catch (e) {
console.log(e);
}
Раньше был и Node.js exists()
, но сейчас он уже официально устарел и не поддерживается.