Подробное объяснение API модуля fs в Node.

Node.js внешний интерфейс Операционная система Promise

обзор фс

В 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читать.

Синхронное чтение 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документ:

Асинхронное чтение readFile
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записывать.

Синхронная запись 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(ошибка), функция обратного вызова выполняется после успешной записи файла в данные.

Асинхронная запись writeFile
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В добавлении пишет "мир".

Синхронизировать добавление 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(ошибка), функция обратного вызова выполняется после успешного добавления данных записи в файл.

Асинхронное добавление appendFile
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Первые два параметра одинаковы, а последний параметр — это функция обратного вызова, которая выполняется после завершения копирования.

Асинхронное копирование copyFile
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".

Получить объект Stats синхронно
const fs = require("fs");

let statObj = fs.statSync("a/b/c.txt");
console.log(statObj.size); // 6

(2) Асинхронно получить статистику метода объекта Stats

statПервый параметр метода — это путь к каталогу, последний параметр — функция обратного вызова, а функция обратного вызова имеет два параметра.err(ошибка) иStatsобъект при чтении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;

Рекурсивное удаление файловых каталогов - асинхронный async/await
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способ решить.


Оригинальный текст взят с: https://www.pandashen.com