Файлы¶
Для работы с файлами в 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()
, но сейчас он уже официально устарел и не поддерживается.