обзор фс
В NodeJS все операции с файлами выполняются черезfs
Он реализуется основным модулем, включая создание, удаление, запрос файловых каталогов, а также чтение и запись файлов.fs
В модуле все методы разделены на две реализации, синхронную и асинхронную, сsync
Постфиксные методы являются синхронными методами и не имеютsync
Метод суффикса является асинхронным методом.Прежде чем понять метод работы с файлом, необходимо предварительно узнать о системе и файле, например, о битах разрешений файла.mode
, идентификационный битflag
, файловый дескрипторfd
подожди, так в пониманииfs
Эти понятия будут разъяснены перед методом.
битовый режим разрешения
потому чтоfs
Модуль должен работать с файлом, что повлечет за собой проблему разрешений на операции, поэтому вам нужно знать, что такое права доступа к файлу и какие у них есть разрешения.
Таблица прав доступа к файлам:
Назначение разрешений | владелец файла | группа, к которой принадлежит файл | другие пользователи | ||||||
---|---|---|---|---|---|---|---|---|---|
элемент разрешения | читать | Напишите | воплощать в жизнь | читать | Напишите | воплощать в жизнь | читать | Напишите | воплощать в жизнь |
представление символов |
r | w | x | r | w | x | r | w | x |
цифровое представление | 4 | 2 | 1 | 4 | 2 | 1 | 4 | 2 | 1 |
В приведенной выше таблице мы видим, что система выделяет разрешения для трех типов, а именно владельца файла (я), группы, к которой принадлежит файл (семья), и других пользователей (чужих). права доступа Чтение, запись и выполнение, числа выражаются как восьмеричные числа, а восьмеричные числа с разрешениями соответственно4
,2
,1
, не имеет разрешения на0
.
Чтобы было легче понять, мы можем открыть его в любом каталогеGit
, с помощью команды Linuxls -al
Чтобы проверить биты разрешений файлов и папок в каталоге, еслиGit
а такжеLinux
Команда не знакома, вы можете видетьКраткое изложение команд Git, от нуля до знакомых (полностью).
drwxr-xr-x 1 PandaShen 197121 0 28 июня 14:41 core
-rw-r--r-- 1 PandaShen 197121 293 23 июн 17:44 index.md
В приведенной выше информации о каталоге легко увидеть такую информацию, как имя пользователя, время создания и имя файла, но самое главное — это первый элемент (десять символов).
Первый представляет, является ли это файлом или папкой,d
Начало представляет собой папку,-
Начало представляет файл, а следующие девять представляют биты разрешений текущего пользователя, группы, к которой принадлежит пользователь, и других пользователей, разделенные на три, представляющие чтение (r), запись (w) и выполнение (x). ), соответственно.-
Указывает, что нет разрешения, соответствующего текущему биту.
Параметры разрешенийmode
В основном для операционных систем Linux и Unix разрешения Window по умолчанию доступны для чтения, записи и неисполняемого, поэтому количество битов разрешения выражается как0o666
, преобразованный в десятичное представление как438
.
r | w | — | r | — | — | r | — | — |
---|---|---|---|---|---|---|---|---|
4 | 2 | 0 | 4 | 0 | 0 | 4 | 0 | 0 |
6 | 4 | 4 |
флаг
В NodeJS флаг представляет режим работы файла, например, доступный для чтения, записи, доступный как для чтения, так и для записи и т. д. Далее таблица используется для представления флага операции с файлом и его соответствующего значения.
символ | имея в виду |
---|---|
r | Прочитайте файл и создайте исключение, если файл не существует. |
r+ | Прочитайте и запишите файл, создав исключение, если файл не существует. |
rs | Чтение и запись файлов, указывающие на то, что операционная система накручивает кэш локальной файловой системы. |
w | Запись в файл. Если файл не существует, он будет создан. Если он существует, он будет очищен и записан. |
wx | Записать в файл, открыть монопольно. |
w+ | Прочитайте и запишите файл, создайте файл, если он не существует, и запишите его после его очистки, если он существует. |
wx+ | а такжеw+ Точно так же открыть монопольно. |
a | Добавить запись, если файл не существует, создать файл. |
ax | а такжеa Точно так же открыть монопольно. |
a+ | Прочитайте и добавьте запись, создайте, если она не существует. |
ax+ | а такжеa+ Точно так же открыть монопольно. |
В приведенной выше таблице показаны конкретные символы и значения этих идентификационных битов, ноflag
Он используется нечасто и его нелегко запомнить, поэтому ниже приводится краткое описание метода ускорения запоминания.
- р: читать
- ж: пиши
- с: синхронизировать
- +: увеличить противоположную операцию
- x: эксклюзивный способ
r+
а такжеw+
Разница, когда файл не существует,r+
Файл не создается, выбрасывается исключение, ноw+
создаст файл; если файл существует,r+
не будет автоматически очищать файл, ноw+
Содержимое существующих файлов будет автоматически удалено.
файловый дескриптор fd
Операционная система присваивает каждому открытому файлу числовой идентификатор, называемый файловым дескриптором. Файловые операции используют эти файловые дескрипторы для идентификации и отслеживания каждого конкретного файла. Система Windows использует другой, но концептуально похожий механизм для отслеживания. Ресурсы. Для удобства пользователей NodeJS абстрагируется от различий между разными операционными системами и присваивает числовые файловые дескрипторы всем открытым файлам.
В NodeJS каждый раз при работе с файлом дескриптор файла увеличивается, и дескриптор файла обычно начинается с3
начать, потому что предыдущий0
,1
,2
Еще три специальных дескриптора, представляющихprocess.stdin
(стандартный ввод),process.stdout
(стандартный вывод) иprocess.stderr
(вывод ошибки).
Основные методы работы с файлами
Основные методы файловых операций заключаются в выполнении общих операций над файлом, то есть все данные файла непосредственно помещаются в память для выполнения таких операций, как чтение, запись, копирование и добавление.Из-за ограниченного объема памяти компьютера , для операций с файлами необходимо учитывать производительность, поэтому эти методы подходят только для файлов, операции с которыми занимают меньше памяти.
1. Чтение файла
(1) Метод синхронного чтения readFileSync
readFileSync
Есть два параметра:
- Первый параметр — это путь или файловый дескриптор прочитанного файла;
- Второй параметр
options
, значение по умолчаниюnull
,Включаяencoding
(кодировка, по умолчаниюnull
)а такжеflag
(Бит идентификатора, по умолчаниюr
), или напрямуюencoding
; - Возвращаемое значение — содержимое файла, если его нет.
encoding
, содержимое возвращаемого файла — Buffer, если оно анализируется в соответствии с входящей кодировкой.
Если теперь есть файл с именем1.txt
, содержание «Привет», теперь используйтеreadFileSync
читать.
const fs = require("fs");
let buf = fs.readFileSync("1.txt");
let data = fs.readFileSync("1.txt", "utf8");
console.log(buf); // <Buffer 48 65 6c 6c 6f>
console.log(data); // Hello
(2) Метод асинхронного чтения readFile
Метод асинхронного чтенияreadFile
а такжеreadFileSync
Первые два параметра одинаковы, последний параметр — это функция обратного вызова, а в функции два параметра.err
(ошибка) иdata
(данные), этот метод не имеет возвращаемого значения, а функция обратного вызова выполняется после успешного чтения файла.
все еще читаю1.txt
документ:
const fs = require("fs");
fs.readFile("1.txt", "utf8", (err, data) => {
console.log(err); // null
console.log(data); // Hello
});
2. Запись файла
(1) Метод синхронной записи writeFileSync
writeFileSync
Есть три параметра:
- Первый параметр — это путь или файловый дескриптор для записи в файл;
- Второй параметр — записываемые данные, тип — String или Buffer;
- Третий параметр
options
, значение по умолчаниюnull
,Включаяencoding
(кодировка, по умолчаниюutf8
),flag
(Бит идентификатора, по умолчаниюw
)а такжеmode
(бит разрешения, по умолчанию0o666
), или напрямуюencoding
.
Если теперь есть файл с именем2.txt
, содержимое "12345", теперь используйтеwriteFileSync
записывать.
const fs = require("fs");
fs.writeFileSync("2.txt", "Hello world");
let data = fs.readFileSync("2.txt", "utf8");
console.log(data); // Hello world
(2) Метод асинхронной записи writeFile
Метод асинхронной записиwriteFile
а такжеwriteFileSync
Первые три параметра одинаковые, последний параметр — функция обратного вызова, и в функции есть один параметрerr
(ошибка), функция обратного вызова выполняется после успешной записи файла в данные.
const fs = require("fs");
fs.writeFile("2.txt", "Hello world", err => {
if (!err) {
fs.readFile("2.txt", "utf8", (err, data) => {
console.log(data); // Hello world
});
}
});
3. Файл добавить запись
(1) Синхронный метод записи добавления appendFileSync
appendFileSync
Есть три параметра:
- Первый параметр — это путь или файловый дескриптор для записи в файл;
- Второй параметр — записываемые данные, тип — String или Buffer;
- Третий параметр
options
, значение по умолчаниюnull
,Включаяencoding
(кодировка, по умолчаниюutf8
),flag
(Бит идентификатора, по умолчаниюa
)а такжеmode
(бит разрешения, по умолчанию0o666
), или напрямуюencoding
.
Если теперь есть файл с именем3.txt
, содержание «Привет», теперь используйтеappendFileSync
В добавлении пишет "мир".
const fs = require("fs");
fs.appendFileSync("3.txt", " world");
let data = fs.readFileSync("3.txt", "utf8");
console.log(data); // Hello world
(2) Асинхронный метод записи добавления appendFile
Метод асинхронной записи добавленияappendFile
а такжеappendFileSync
Первые три параметра одинаковые, последний параметр — функция обратного вызова, и в функции есть один параметрerr
(ошибка), функция обратного вызова выполняется после успешного добавления данных записи в файл.
const fs = require("fs");
fs.appendFile("3.txt", " world", err => {
if (!err) {
fs.readFile("3.txt", "utf8", (err, data) => {
console.log(data); // Hello world
});
}
});
4. Скопируйте файл и напишите
(1) Метод синхронного копирования copyFileSync
Синхронный метод записи копииcopyFileSync
Есть два параметра, первый параметр — это путь к исходному файлу, который нужно скопировать, а второй параметр — это путь к целевому файлу, который нужно скопировать.Если целевой файл не существует, он будет создан и скопирован.
Теперь поместите выше3.txt
скопируйте содержимое в4.txt
середина:
const fs = require("fs");
fs.copyFileSync("3.txt", "4.txt");
let data = fs.readFileSync("4.txt", "utf8");
console.log(data); // Hello world
(2) Метод асинхронного копирования copyFile
Асинхронный метод записи копииcopyFile
а такжеcopyFileSync
Первые два параметра одинаковы, а последний параметр — это функция обратного вызова, которая выполняется после завершения копирования.
const fs = require("fs");
fs.copyFile("3.txt", "4.txt", () => {
fs.readFile("4.txt", "utf8", (err, data) => {
console.log(data); // Hello world
});
});
(3) Имитация синхронного и асинхронного копирования и записи в файлы
использоватьreadFileSync
а такжеwriteFileSync
Вы можете имитировать синхронное копирование и запись в файлы, используяreadFile
а такжеwriteFile
Вы можете имитировать асинхронную запись для копирования файлов, код выглядит следующим образом:
const fs = require("fs");
function copy(src, dest) {
let data = fs.readFileSync(src);
fs.writeFileSync(dest, data);
}
// 拷贝
copy("3.txt", "4.txt");
let data = fs.readFileSync("4.txt", "utf8");
console.log(data); // Hello world
const fs = require("fs");
function copy(src, dest, cb) {
fs.readFile(src, (err, data) => {
// 没错误就正常写入
if (!err) fs.writeFile(dest, data, cb);
});
}
// 拷贝
copy("3.txt", "4.txt", () => {
fs.readFile("4.txt", "utf8", (err, data) => {
console.log(data); // Hello world
});
});
Расширенные методы для файловых операций
1. Откройте файл open
open
Метод имеет четыре параметра:
- путь: путь к файлу;
- флаг: бит флага;
- режим: биты разрешения, по умолчанию
0o666
; - callback: функция обратного вызова с двумя параметрами
err
(ошибка) иfd
(файловый дескриптор), выполняемый после открытия файла.
const fs = require("fs");
fs.open("4.txt", "r", (err, fd) => {
console.log(fd);
fs.open("5.txt", "r", (err, fd) => {
console.log(fd);
});
});
// 3
// 4
2. Закройте файл закрыть
close
Метод имеет два параметра, первый параметр — файловый дескриптор закрытого файла.fd
, второй параметр - функция обратного вызова, функция обратного вызова имеет один параметрerr
(ошибка), выполняемая после закрытия файла.
const fs = require("fs");
fs.open("4.txt", "r", (err, fd) => {
fs.close(fd, err => {
console.log("关闭成功");
});
});
// 关闭成功
3. Прочитать прочитанный файл
read
метод сreadFile
Другое дело, как правило, в случае, если файл слишком велик для чтения всего содержимого в кэш за один раз или размер файла неизвестен, он считывается в буфер несколько раз.
Дополнительные сведения о буфере см.NodeJS — интерпретация буфера.
read
В методе шесть параметров:
- fd: файловый дескриптор, необходимо использовать первым
open
Открыть; - буфер: Буфер для чтения содержимого;
- смещение: целое число, начальная позиция для записи в буфер;
- length: целое число, длина прочитанного файла;
- position: целое число, прочитать начальную позицию файла;
- callback: функция обратного вызова с тремя параметрами
err
(ошибка),bytesRead
(количество фактически прочитанных байтов),buffer
(объект буфера для записи), выполняемый после завершения чтения.
Прочитайте один ниже6.txt
файл с содержимым «Здравствуйте».
const fs = require("fs");
let buf = Buffer.alloc(6);
// 打开文件
fs.open("6.txt", "r", (err, fd) => {
// 读取文件
fs.read(fd, buf, 0, 3, 0, (err, bytesRead, buffer) => {
console.log(bytesRead);
console.log(buffer);
// 继续读取
fs.read(fd, buf, 3, 3, 3, (err, bytesRead, buffer) => {
console.log(bytesRead);
console.log(buffer);
console.log(buffer.toString());
});
});
});
// 3
// <Buffer e4 bd a0 00 00 00>
// 3
// <Buffer e4 bd a0 e5 a5 bd>
// 你好
4. Синхронизируйте дисковый кеш fsync
fsync
Метод имеет два параметра, первый параметр — дескриптор файла.fd
, второй параметр это функция обратного вызова, в функции обратного вызова есть один параметрerr
(Ошибка), выполняется после синхронизации кеша диска.
В использованииwrite
Когда метод записывает данные в файл, поскольку это не однократная запись, последняя запись должна синхронизировать кэш диска перед закрытием файла.fsync
метод будет сопоставлен позжеwrite
использовать вместе.
5. Запись в файл write
write
метод сwriteFile
Отличие в том,что данные в Буфере записываются в файл.Функция Буфера-станция передачи данных.Может источник данных занимает слишком много памяти или память неопределенная,и в память не записывается за один раз, так написано сегментами.больше сread
метод совпадает.
write
В методе шесть параметров:
- fd: файловый дескриптор, необходимо использовать первым
open
Открыть; - буфер: Буфер, в котором хранятся данные для записи в файл;
- смещение: целое число, начальная позиция чтения данных из буфера;
- длина: целое число, количество байтов для чтения данных буфера;
- position: целое число, начальная позиция файла записи;
- callback: функция обратного вызова с тремя параметрами
err
(ошибка),bytesWritten
(количество фактически записанных байтов),buffer
(объект буфера читается), выполняется после завершения записи.
Следующее запишет два слова в середине буфера в файл6.txt
, исходное содержание — «Привет».
const fs = require("fs");
let buf = Buffer.from("你还好吗");
// 打开文件
fs.open("6.txt", "r+", (err, fd) => {
// 读取 buf 向文件写入数据
fs.write(fd, buf, 3, 6, 3, (err, bytesWritten, buffer) => {
// 同步磁盘缓存
fs.fsync(fd, err => {
// 关闭文件
fs.close(fd, err => {
console.log("关闭文件");
});
});
});
});
// 这里为了看是否写入成功简单粗暴的使用 readFile 方法
fs.readFile("6.txt", "utf8", (err, data) => {
console.log(data);
});
// 你还好
Приведенный выше код читает «Вы в порядке» в середине «Вы в порядке» из буфера и записывает его в6.txt
После слова «Вы» в файле, но последний «хороший» не сохраняется, это означает, что содержимое после «вы» Word в файле опорожняется перед записью.
6, внедрить COPY для больших файлов
прежде чем мы использовалиreadFile
а такжеwriteFile
понялcopy
функция, чтоcopy
Функция состоит в том, чтобы одновременно считывать данные скопированного файла в память и одновременно записывать их в целевой файл для небольших файлов.
Если нереально записать большой файл за один раз, нужно читать и писать несколько раз.Далее использовать вышеуказанные методы для реализации большого файла и размер файла неизвестен.copy
функция.
// copy 方法
function copy(src, dest, size = 16 * 1024, callback) {
// 打开源文件
fs.open(src, "r", (err, readFd) => {
// 打开目标文件
fs.open(dest, "w", (err, writeFd) => {
let buf = Buffer.alloc(size);
let readed = 0; // 下次读取文件的位置
let writed = 0; // 下次写入文件的位置
(function next() {
// 读取
fs.read(readFd, buf, 0, size, readed, (err, bytesRead) => {
readed += bytesRead;
// 如果都不到内容关闭文件
if(!bytesRead) fs.close(readFd, err => console.log("关闭源文件"));
// 写入
fs.write(writeFd, buf, 0, bytesRead, writed, (err, bytesWritten) => {
// 如果没有内容了同步缓存,并关闭文件后执行回调
if (!bytesWritten) {
fs.fsync(writeFd, err => {
fs.close(writeFd, err => return !err && callback());
});
}
writed += bytesWritten;
// 继续读取、写入
next();
}
);
});
})();
});
});
}
надcopy
В методе мы вручную сохраняем следующую позицию чтения и следующую позицию записи, если параметрreaded
а такжеwrited
место входящегоnull
, NodeJS автоматически поможет нам сохранить эти два значения.
Теперь есть файл6.txt
Содержимое "привет", пустой файл7.txt
,мы будем6.txt
напишите содержание7.txt
середина.
const fs = require("fs");
// buffer 的长度
const BUFFER_SIZE = 3;
// 拷贝文件内容并写入
copy("6.txt", "7.txt", BUFFER_SIZE, () => {
fs.readFile("7.txt", "utf8", (err, data) => {
// 拷贝完读取 7.txt 的内容
console.log(data); // 你好
});
});
При выполнении операций с файлами в NodeJS при многократном чтении и записи размер данных, считываемых за раз, обычно64k
, размер записываемых данных16k
.
Метод работы с каталогом файлов
Следующие методы работы с файловыми каталогами имеют одну общую черту: первый переданный параметр — это путь к файлу, например:a/b/c/d
, также делится на две реализации: синхронную и асинхронную.
1. Просмотр прав доступа к файловому каталогу
(1) Метод разрешения синхронного просмотра accessSync
accessSync
Метод передает путь к каталогу и проверяет, доступен ли каталог по входящему пути для чтения и записи.Если есть разрешение на операцию, возвращаемое значение отсутствует.Если нет разрешения или путь недопустим,Error
объект, так что используйте его большеtry...catch...
Перехват исключения.
const fs = require("fs");
try {
fs.accessSync("a/b/c");
console.log("可读可写");
} catch (err) {
console.error("不可访问");
}
(2) Доступ к методу разрешения асинхронной операции просмотра
access
Метод и первый параметр — это путь к каталогу, последний параметр — функция обратного вызова, а функция обратного вызова имеет параметрerr
(ошибка), срабатывает после обнаружения разрешения, если разрешение доступноerr
дляnull
Нет власти или пути незаконныerr
ЯвляетсяError
объект.
const fs = require("fs");
fs.access("a/b/c", err => {
if (err) {
console.error("不可访问");
} else {
console.log("可读可写");
}
});
2. Получите объект Stats каталога файлов
каталог файловStats
Объект хранит некоторую важную информацию о файле или папке, такую как время создания, время последнего доступа, время последней модификации, количество байтов, занимаемых статьей, а также несколько методов определения типа файла и т. д.
(1) Синхронно получить метод объекта Stats statSync
statSync
Параметр метода — это путь к каталогу, а возвращаемое значение — это путь к текущему каталогу.Stats
объект, теперь черезStats
приобретение объектаa
в каталогеb
в каталогеc.txt
Размер файла в байтах и содержимое файла "Hello".
const fs = require("fs");
let statObj = fs.statSync("a/b/c.txt");
console.log(statObj.size); // 6
(2) Асинхронно получить статистику метода объекта Stats
stat
Первый параметр метода — это путь к каталогу, последний параметр — функция обратного вызова, а функция обратного вызова имеет два параметра.err
(ошибка) иStats
объект при чтенииStats
После выполнения также реализуется приведенный выше пример чтения количества байт файла.
const fs = require("fs");
fs.stat("a/b/c.txt", (err, statObj) => {
console.log(statObj.size); // 6
});
3. Создайте каталог файлов
(1) Метод синхронного создания каталога mkdirSync
mkdirSync
Параметр метода — это путь к каталогу, и возвращаемого значения нет.В процессе создания каталога необходимо убедиться, что файлы и каталоги перед входящим путем существуют, иначе будет выдано исключение.
const fs = require("fs");
// 假设已经有了 a 文件夹和 a 下的 b 文件夹
fs.mkdirSync("a/b/c");
(2) Метод асинхронного создания каталога mkdir
mkdir
Первый параметр метода — это путь к каталогу, последний параметр — функция обратного вызова, а функция обратного вызова имеет один параметр.err
(ошибка), выполняемая после операции создания, также требует, чтобы папки в начале пути существовали.
const fs = require("fs");
// 假设已经有了 a 文件夹和 a 下的 b 文件夹
fs.mkdir("a/b/c", err => {
if (!err) console.log("创建成功");
});
// 创建成功
4. Прочитайте каталог файлов
(1) Метод синхронного чтения каталога readdirSync
readdirSync
Метод имеет два параметра:
- Первый параметр - это путь к каталогу.Каталог перед входящим путем должен существовать, иначе будет сообщено об ошибке;
- Второй параметр
options
,Включаяencoding
(кодировка, по умолчаниюutf8
), или напрямуюencoding
; - Возвращаемое значение представляет собой массив, в котором хранятся имена элементов в каталоге файлов.
Предположим, что он уже существуетa
каталог иa
внизb
содержание,b
в каталогеc
каталог иindex.js
файл, прочтите структуру каталогов файлов ниже.
const fs = require("fs");
let data = fs.readdirSync("a/b");
console.log(data); // [ 'c', 'index.js' ]
(2) Метод асинхронного чтения каталога readdir
readdir
Первые два параметра метода такие же, какreaddirSync
То же самое, третий параметр - callback-функция, а callback-функция имеет два параметраerr
(ошибка) иdata
(массив, хранящий имена элементов в каталоге файлов), выполняемый после чтения каталога файлов.
Приведенный выше случай записывается асинхронно:
const fs = require("fs");
fs.readdir("a/b", (err, data) => {
if (!err) console.log(data);
});
// [ 'c', 'index.js' ]
5. Удалите каталог файлов
Будь то синхронно или асинхронно, при удалении директории с файлами необходимо убедиться, что путь к директории с файлами существует, а директория с удаляемыми файлами пуста, то есть в ней нет папок и файлов.
(1) Метод синхронного удаления каталога rmdirSync
rmdirSync
Аргумент — это путь к удаляемому каталогу, который сейчас существует.a
каталог иa
в каталогеb
каталог, удалитьb
содержание.
const fs = require("fs");
fs.rmdirSync("a/b");
(2) Метод асинхронного удаления каталога rmdir
rmdir
Первый параметр метода такой же, какrmdirSync
То же самое, последний параметр - функция обратного вызова, в функции есть параметрerr
(ошибка), выполняемая после операции удаления каталога.
const fs = require("fs");
fs.rmdir("a/b", err => {
if (!err) console.log("删除成功");
});
// 删除成功
6. Операция удаления файла
(1) Метод синхронного удаления файла unlinkSync
unlinkSync
Аргумент - это путь к удаляемому файлу, который сейчас существуетa
каталог иa
в каталогеindex.js
файл, удалитьindex.js
документ.
const fs = require("fs");
fs.unlinkSync("a/inde.js");
(2) Метод асинхронного удаления файла unlink
unlink
Первый параметр метода такой же, какunlinkSync
То же самое, последний параметр - функция обратного вызова, в функции есть параметрerr
(Ошибка), выполняемая после операции удаления файла.
const fs = require("fs");
fs.unlink("a/index.js", err => {
if (!err) console.log("删除成功");
});
// 删除成功
Реализовать рекурсивное создание каталога
Мы создаем функцию, параметр — это путь, и создаем папку каталога уровень за уровнем в соответствии с путем.
1. Реализация синхронизации
const fs = require("fs");
const path = require("path");
// 同步创建文件目录
function mkPathSync(dirPath) {
// path.sep 文件路径分隔符(mac 与 window 不同)
// 转变成数组,如 ['a', 'b', 'c']
let parts = dirPath.split(path.sep);
for(let i = 1; i <= parts.length; i++) {
// 重新拼接成 a a/b a/b/c
let current = parts.slice(0, i).join(path.sep);
// accessSync 路径不存在则抛出错误在 catch 中创建文件夹
try {
fs.accessSync(current);
} catch(e) {
fs.mkdirSync(current);
}
}
}
// 创建文件目录
mkPathSync(path.join("a", "b", "c"));
Синхронный код должен использоватьaccessSync
способ проверить, существует ли путь к файлу, используйтеtry...catch...
Выполните захват ошибок, если путь не существует, будет сообщено об ошибке, и запись будетcatch
Завершите создание папки.
2. Реализация асинхронного обратного вызова
const fs = require("fs");
const path = require("path");
function mkPathAsync(dirPath, callback) {
// 转变成数组,如 ['a', 'b', 'c']
let parts = dirPath.split(path.sep);
let index = 1;
// 创建文件夹方法
function next() {
// 重新拼接成 a a/b a/b/c
let current = parts.slice(0, index).join(path.sep);
index++;
// 如果路径检查成功说明已经有该文件目录,则继续创建下一级
// 失败则创建目录,成功后递归 next 创建下一级
fs.access(current, err => {
if (err) {
fs.mkdir(current, next);
} else {
next();
}
});
}
next();
}
// 创建文件目录
mkPathAsync(path.join("a", "b", "c"), () => {
console.log("创建文件目录完成")
});
// 创建文件目录完成
В приведенном выше методе сращивание каждого каталога осуществляется не зацикливанием, а с помощью рекурсивных внутренних функций.next
способ и поддерживатьindex
Переменные реализованы, используяaccess
Когда он успешно указывает, что файловый каталог уже существует, продолжайте рекурсивно создавать следующий уровень, если он существует.err
Если описания нет, создайте папку.
3. Реализация асинхронного async/await
Вышеупомянутые два метода, синхронный код блокировки, низкая производительность, производительность вложения асинхронной функции обратного вызова хорошая, но плохое обслуживание, мы хотим иметь хорошую производительность, хорошую читаемость кода, теперь мы можем использовать популярный NodeJSasync/await
способ асинхронного программирования, хотел бы знатьasync/await
можно смотретьПроцесс асинхронной разработки — главный трюк асинхронного программирования async/awaitЭта статья.
использоватьasync
в функцииawait
Асинхронные операции, которые ждут, должны быть преобразованы в промисы, которые мы все использовали раньше.util
под модульpromisify
метод преобразования, на самом делеpromisify
Принцип метода очень прост, сначала реализуем рекурсивное создание файловой директорииpromisify
метод.
// 将一个异步方法转换成 Promise
function promisify(fn) {
return function (...args) {
return new Promise((resolve, reject) => {
fn.call(null, ...args, err => err ? reject() : resolve());
});
}
}
фактическиpromisify
Метод реализован с помощью замыканий, а при вызове передается функция, которую нужно преобразовать в Promise.fn
, возвращает функцию закрытия, возвращает экземпляр Promise в функции закрытия и выполняет его синхронноfn
,пройти черезcall
Параметры функции закрытия и функции обратного вызова передаются как параметрыfn
, Обратный вызов вызывается экземплярами Promise, когда возникает ошибка вreject
, иначе позвонитеresolve
;
const fs = require("fs");
const path = require("path");
// 将 fs 中用到的方法转换成 Promise
const access = promisify(fs.access);
const mkdir = promisify(fs.mkdir);
// async/await 实现递归创建文件目录
async function mkPath(dirPath) {
// 转变成数组,如 ['a', 'b', 'c']
let parts = dirPath.split(path.sep);
for(let i = 1; i <= parts.length; i++) {
// 重新拼接成 a a/b a/b/c
let current = parts.slice(0, i).join(path.sep);
// accessSync 路径不存在则抛出错误在 catch 中创建文件夹
try {
await access(current);
} catch(e) {
await mkdir(current);
}
}
}
// 创建文件目录
mkPath(path.("a", "b", "c")).then(() => {
console.log("创建文件目录完成");
});
// 创建文件目录完成
использоватьasync/await
Код больше похож на синхронную реализацию, но выполняется асинхронно, поэтому учитывается и производительность, и читабельность кода.Преимущества очевидны.При использовании фреймворка NodeJSKoa 2.x
Этот метод часто используется для асинхронного программирования.
Суммировать
существуетfs
Все модули имеют как синхронную, так и асинхронную реализации. Характеристика синхронного метода заключается в том, что он блокирует код, что приводит к низкой производительности. Характеристикой асинхронного кода является наличие множества вложенных функций обратного вызова.fs
Вы должны попытаться использовать асинхронное программирование для обеспечения производительности.Если вы чувствуете, что вложенность функций обратного вызова нелегко поддерживать, вы можете использовать Promise иasync/await
способ решить.