Создать папку
Предположим, мы хотим создать такую папку «a/b/c/d/e».
Синхронное создание папок
let fs = require('fs');
function makep(dir) {
let paths = dir.split('/');
for(let i =1;i<paths.length;i++){
let newPath = paths.slice(0,i).join('/');
try{
//是否能访问到这个文件,如果能访问到,说明这个文件已经存在,进入循环的下一步。
//accessSync的第二个参数就是用来判断该文件是否能被读取
fs.accessSync(newPath,fs.constants.R_OK);
}catch (e){
fs.mkdirSync(newPath);
}
}
}
makep('a/d/c/d/e')
Синхронное создание будет иметь проблемы с производительностью, поэтому этот метод создания не рекомендуется, лучше использовать асинхронное создание.
Создать папку асинхронно
Мы используем рекурсию для создания папок
function mkdirSync(dir,cb) {
let paths = dir.split('/');
let index =1;
function next(index) {
//递归结束判断
if(index>paths.length)return cb();
let newPath = paths.slice(0,index).join('/');
fs.access(newPath,function (err) {
if(err){//如果文件不存在,就创建这个文件
fs.mkdir(newPath,function (err) {
next(index+1);
});
}else{
//如果这个文件已经存在,就进入下一个循环
next(index+1);
}
})
}
next(index);
}
mkdirSync('a/b/c/d/e',function () {
console.log('创建成功')
})
удалить папку
Прежде всего, мы должны сначала определить, является ли файл непустым файлом; если это пустой файл, удалить его, если он не пустой, то удалить дочерний файл, пока родительский файл не будет пуст, а затем удалить родительский файл.
Синхронизировать удаление папок
function removeDir(dir) {
let files = fs.readdirSync(dir)
for(var i=0;i<files.length;i++){
let newPath = path.join(dir,files[i]);
let stat = fs.statSync(newPath)
if(stat.isDirectory()){
//如果是文件夹就递归下去
removeDir(newPath);
}else {
//删除文件
fs.unlinkSync(newPath);
}
}
fs.rmdirSync(dir)//如果文件夹是空的,就将自己删除掉
}
removeDir('a');
Асинхронно удалить папку
promise版
function removePromise(dir) {
return new Promise(function (resolve, reject) {
//先读文件夹
fs.stat(dir,function (err, stat) {
if(stat.isDirectory()){
fs.readdir(dir,function (err, files) {
files = files.map(file=>path.join(dir,file)); // a/b a/m
files = files.map(file=>removePromise(file)); //这时候变成了promise
Promise.all(files).then(function () {
fs.rmdir(dir,resolve);
})
})
}else {
fs.unlink(dir,resolve)
}
})
})
}
removePromise('a').then(function () {
console.log('删除成功')
})
Асинхронное удаление - обход в глубину
Основная идея глубины сначала - "не бейся о южную стену, не оглядывайся", "в один конец в темноту", если встретишь "стену" или "нет пути", иди к следующий способ. Итак, порядок удаления файлов4->5->3->6->2->7->10->11->9->12->8->1
Мы делаем это с помощью кода
let fs = require('fs');
let path = require('path');
function rmdir(dir,cb) {
fs.readdir(dir,function (err, files) {
next(0);
function next(index) {
if(index == files.length)
return fs.rmdir(dir,cb);
let newPath = path.join(dir,files[index]);
console.log(newPath)
fs.stat(newPath,function (err, stat) {
if(err){
console.log(err);
}
if(stat.isDirectory()){
// 在这里完成深度优先,一层层往下找,直到找到非空文件夹
rmdir(newPath,()=>next(index+1));
}else {
// 删除文件
fs.unlink(newPath,function (err) {
if (err) {
console.error(err);
}
next(index + 1);
});
}
})
}
})
}
rmdir('a',function () {
console.log('删除成功')
});
Асинхронное удаление — сначала в ширину
В ширину сначала нужно начать с корневого узла и пройти узлы дерева по ширине дерева.Если цель найдена, исчисление прекращается.
let fs = require('fs');
let path = require('path');
function wide(dir,cb){
let arrs = [dir];
let index = 0;
function rmdir() {
console.log(arrs)
let current = arrs[--index];
if (current) {
fs.stat(current, (err, stat) => {
if (stat.isDirectory()) {
fs.rmdir(current, rmdir);
} else {
fs.unlink(current, rmdir)
}
})
}
}
!function next(){
if(index === arrs.length) {return rmdir();}
let current = arrs[index++];
fs.stat(current,function(err,stat){
if(stat.isDirectory()){
fs.readdir(current,function(err,files){
arrs = [...arrs,...files.map(file=>
path.join(current,file);
})]; // ['a','a/b','a/c','a/b/d','a/c/e'];
next();
});
}else{
next();
}
})
}()
}
wide('a',function () {
console.log('删除成功')
});
Эпилог
Вышеуказанные функции часто используют рекурсию, и если вы мало что знаете о рекурсии, вам будет сложно ее понять.