обзор фс
В 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способ решить.