Оглавление
Доброго времени суток, друзья. Поговорим сегодня о работе с файлами в Node.js. Для работы с файлами используется модуль fs (сокращение от File System).
В этой статье мы рассмотрим следующие темы:
— Работа с файловыми дескрипторами;
— Работа с директориями;
— Создание новой папки;
— Чтение содержимого папки;
— Удаление папки;
— Получение системной информации о файле;
— Модуль path и путь к файлу;
— Получение имени, пути и расширения файла;
— Работа с путями файла;
— Переименование файла или директории;
— Чтение файла;
— Запись файла;
— Копирование файла;
— Удаление файла.
Для начала работы нам потребуется установленная Node.js. Подробную инструкцию по ее установке вы можете получить (тут).
Прежде чем начать работу с модулем, его следует импортировать в рабочем файле.
Пример:
const fs = require(‘fs');
Пробежимся по основным методам этого модуля и посмотрим на примерах как с ними можно работать.
Работа с файловыми дескрипторами
Прежде чем двигаться дальше, давайте посмотрим на термины, о которых описано в статье ниже.
Файловый дескриптор — это неотрицательное целое число. Когда создается новый поток ввода-вывода, ядро возвращает процессу, создавшему поток ввода-вывода, его файловый дескриптор (Wikipedia).
Если излагать простыми словами, то при открытии файла мы получаем его дескриптор — это уникальный индикатор, благодаря которому мы можем отслеживать каждый файл отдельно и работать с ним. Для получения дескриптора файла в Node.js используются два метода: (1) асинхронный метод fs.open() и (2) синхронный fs.openSync(). К слову все методы в Node.js имеют синхронные и асинхронные реализации. Синхронные методы отмечены в название метода с окончанием Sync. В чем же разница между синхронным и асинхронным методами? Главное отличие — это порядок их выполнения. Синхронный метод будет выполнен путем блокирования основного потока, в тоже время, если для того же действия использовать ассинхронный метод, то операции могут быть выполнены в произвольном порядке по истечению их выполнения (т.к. основной поток не будет блокироваться).
Перейдем к примерам.
const fs = require('fs')
// асинхронный
fs.open('template.txt', 'r', (err, fd) => {
if (err) throw err;
//fd - это дескриптор файла
console.log(fd)
})
// синхронный
try {
const fd = fs.openSync('template.txt', 'r')
console.log(fd)
} catch (err) {
console.error(err)
}
В этих примерах при выполнении кода, мы получим уникальный дескриптор файла. Пройдемся по параметрам методов. Первый — это путь к файлу, который читаем. Второй параметр предназначен для передачи флагов доступа к файлам. В данном примере мы указали параметр ‘r’, что означает этот файл открыт для чтения.
Ниже я приведу перечень флагов доступа к файлам
r — чтение;
r+ — чтение и запись;
w+ — чтение и запись, запись с начала файла. Файл создается если его нет;
a — запись, запись с конца файла. Файл создается если его нет;
a + — чтение и запись, запись с конца файла. Файл создается если его нет;
Третий параметр отличается в зависимости от типа метода. В асинхронном варианте это колбэк функция, первый аргумент которой возвращает ошибку (в случае ее возникновения), а второй — сам дескриптор. Если метод синхронный, то вызов происходит в блоке try/catch для отслеживания ошибок и получения ответа путем присвоения вызова переменной.
Следует помнить, что дескрипторы файлов необходимо закрывать для предотвращения переполнения памяти, а также проблем с производительностью. Выполним данную задачу с помощью метода close() и его синхронного аналога closeSync().
Работа с директориями
Для проверки существующей директории (файла) и доступов к нему в модуле fs применяется метод access
Пример:
const fs = require('fs')
const file = 'package.json';
// проверка существования файла
fs.access(file, fs.constants.F_OK, (err) => {
console.log(`${file} ${err ? 'не существует' : 'существует'}`);
});
// проверка на возможность прочитать файл
fs.access(file, fs.constants.R_OK, (err) => {
console.log(`${file} ${err ? 'не прочитать' : 'прочитать'}`);
});
// проверка на возможность перезаписать файл
fs.access(file, fs.constants.W_OK, (err) => {
console.log(`${file} ${err ? 'не перезаписать' : 'перезаписать'}`);
});
Вторым параметром устанавливается константа режима проверки:
F_OK — существование файла без проверки прав доступа;
R_OK — может ли файл быть прочитан текущим процессом;
W_OK — может ли файл быть записан текущим процессом;
X_OK — может ли файл быть выполнен текущим процессом (в Windows не работает).
Создание новой папки
Для создания каталогов присутствует асинхронный метод mkdir и синхронный mkdirSync.
Пример:
fs.mkdir(__dirname + dir, { recursive: true }, (err) => {
if (err) {
console.error(err)
return
}
})
if (!fs.existsSync(dir)) {
try {
fs.mkdirSync(__dirname + dir, { recursive: true })
} catch (error) {
console.error(error)
}
} else {
console.log('Папка существует')
}
Для создания в текущей директории нового каталога, перед путем следует указать переменную __dirname как вариант реализации абсолютного пути, либо воспользоваться метом resolve модуля path.
Чтение содержимого папки
Для получения содержимого директории используются два метода readdir и readdirSync. Первым параметром для методов передается путь директории, содержимое которой нужно получить.
Пример:
const fs = require('fs')
const dir = __dirname + '/'
fs.readdir(dir, (err, files) => {
if (err) {
console.error(err)
return
}
console.log(files)
})
try {
const files = fs.readdirSync(dir)
console.log(files)
} catch (error) {
console.error(error)
}
Удаление папки
Удаление директории производится с помощью методов rmdir и rmdirSync. Первым параметром методов является путь удаляемой директории.
Пример:
const fs = require('fs')
fs.rmdir(__dirname +'/testDel', () => {
console.log('Файл успешно удален')
})
try {
fs.rmdirSync(__dirname + '/testDel')
console.log('Файл успешно удален')
} catch (error) {
console.error(error)
}
Получение системной информации о файле
Каждый файл, который мы загружаем, помимо данных хранит в себе системную информацию. Для получения этой информации можно воспользоваться методом stat() или выбрать синхронный вариант statSync()
Пример:
// асинхронный
fs.stat('template.txt', (err, stats) => {
if (err) {
console.error(err)
return
}
console.log(stats)
})
// синхронный
try {
const stats = fs.statSync('template.txt')
console.log(stats)
} catch (err) {
console.error(err)
}
Вся информация хранится в получаемом объекте stats. Данный объект хранит в себе методы для получения дополнительной полезной информации.
Перечислю некоторые из этих свойств:
stats.isDirectory() метод позволяет узнать, является ли файл директорией;
stats.isFile() метод возвращает true, если это файл;
stats.isSocket() метод возвращает true, если это сокет;
stats.isSymbolicLink() метод возвращает true, если файл является символьной ссылкой;
stats.size свойство, которое возвращает размер файла;
stats.birthtime возвращает время и дату, когда данный файл был создан.
Пример:
fs.stat('template.txt', (err, stats) => {
if (err) {
console.error(err)
return
}
console.log(stats.isDirectory())
console.log(stats.isFile())
console.log(stats.isSocket())
console.log(stats.isSymbolicLink())
console.log(stats.size)
console.log(stats.mode)
console.log(stats.birthtime)
})
Модуль path и путь к файлу Node.js
Основной проблемой при работе с файлами и папками в операционных системах является разный синтаксис написания путей их расположения. Для решения этой проблемы в Node.js есть модуль path c набором полезных методов.
Для началы работы с модулем его нужно импортировать.
Пример:
const path = require(‘path');
Получение имени, пути и расширения файла
Предположим, что в папке /temp лежит файл template.txt. Воспользуемся методами модуля path для получения имени файла, пути к нему, а так же его расширения.
Пример:
const file = ‘/temp/tempalate.txt'
path.basename(file) // tempalate.txt
Метод basename возвращает наименование файла. Первым параметром передается путь к файлу, вторым параметром (опционально) передается расширение файла, если необходимо получить наименование файла без расширения.
Пример:
path.basename(file, ‘.txt’) // tempalate
path.basename(file, ‘.txt’) // tempalate
Метод dirname возвращает весь путь директории, где лежит файл и имеет один параметр, в который передается путь к файлу.
Пример:
path.dirname(file) // /temp
Метод extname возвращает расширение переданного файла.
Пример:
path.extname(file) // .txt
Работа с путями файла
В модуле path есть ряд методов для удобного формирования путей к нужному файлу или директории. Мы не будем рассматривать все методы, а только наиболее часто используемые. Рассмотрим их ниже.
Метод join принимает список параметров, объединяет их в одну строку, используя разделитель, подходящий к конкретной операционной системе, в которой будет исполнятся код.
Пример:
const folderName = 'temp'
path.join('/', folderName, ‘template.txt') // /temp/template.txt
Метод resolve используется для нахождения абсолютных путей к файлу.
Пример:
path.resolve(‘template.txt') // Users/Desktop/dev/node-fs/template.txt
path.resolve(folderName, ‘template.txt’) // /Users/Desktop/dev/node-fs/temp/template.txt
path.resolve('/temp', ‘template.txt') // /temp/template.txt
Метод normalize позволяет найти путь к файлу, используя синтаксис переходов (.. и .) по папкам.
Пример:
path.normalize(‘/users/../temp/template.txt')
// temp/template.txt
Переименование файла или директории
Методы rename() и renameSync() первым параметром принимают путь к файлу, который нужно переименовать. Второй параметр отвечает за новое наименование файла.
Пример:
const fs = require('fs')
// переименовываем файла
fs.rename('oldFile.txt', 'newFile.txt', (err) => {
if (err) throw err;
console.log('Файл переименован');
});
// переименовываем директорию
try {
fs.renameSync('./oldDir', './newDir')
console.log('Папка переименован');
} catch (error) {
console.error(error)
}
Чтение файла
Пример:
const fs = require('fs')
// асинхронное
fs.readFile(‘template.txt', ‘utf-8’, (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data)
})
// синхронное
try {
const data = fs.readFileSync(‘template.txt', 'utf-8')
console.log(data)
} catch (err) {
console.error(err)
}
Если вторым параметром не указана кодировка, то возвращается Buffer. Эти методы полностью загружают файлы в память компьютера, что может сильно отразиться на производительности. Если размер файла большой, то стоит воспользоваться потоками fs.createReadStream()
Запись файла
Чтобы перезаписать контент файлов, используются методы writeFile и writeFileSync. Важный момент! Если файла, контент которого нужно перезаписать, не существует, то он будет создан автоматически.
Пример:
const fs = require('fs')
const content = 'Новый текст'
fs.writeFile('newText.txt', content, (err) => {
if (err) {
console.error(err)
return
}
console.log('файл успешно перезаписан')
})
try {
fs.writeFileSync('newTextTwo.txt', content)
console.log('файл успешно перезаписан')
} catch (err) {
console.error(err)
}
Копирование файла
Методы copyFile() и copyFileSync() первым параметром принимают путь файла для копирования. Второй параметр принимает название пути и нового файла. Третьим параметром является колбэк функция, которая возвращает ошибку.
Пример:
const fs = require('fs')
fs.copyFile('oldFile.txt', 'oldFileTwo.txt', (err) => {
if (err) {
console.error(err)
return
}
console.log('Файл успешно копирован')
});
try {
fs.copyFileSync('oldFile.txt', 'oldFileTwo.txt')
console.log('Файл успешно копирован')
} catch (error) {
console.error(error)
}
Удаление файла
Последнее, что мы рассмотрим в этой статье будут методы unlink() и unlinkSync(). Первым параметром методы принимают путь к удаляемому файлу. Второй параметр в методе unlink возвращает колбэк функцию с ошибкой.
Пример:
const fs = require('fs')
fs.unlink('file.txt', (err) => {
if (err) throw err;
console.log('Файл успешно удален');
});
try {
fs.unlinkSync('file.txt')
console.log('Файл успешно удален');
} catch (error) {
console.error(error)
}
Заключение
В данной статье мы разобрали работу Node.js с файлами, на примерах посмотрели основные полезные методы модулей fs и path. Исходный код вы сможете найти тут. Надеюсь данная статья была вам полезна. Учитесь, думайте, пишите код. Удачного кодинга, друзья!
Полезные ссылки:
https://nodejs.org/en/ — официальный сайт node.js
Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации.
Комментарии: