菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
0
0

Node.JavaScript文件系统中目录的操作

原创
05/13 14:22
阅读数 1975

课程推荐:Java开发工程师--学习猿地--送7个上线商业项目

file
谈到对目录的操作,需要涉及到对目录遍历,其实目录也是我们可以把它看成一颗树。树是一种非线性的数据结构,被用来存储具有层级关系的数据,还被用来存储有序列表,其中有一种特殊的树:二叉树。

有一种特殊的二叉树叫二叉查找树(BST),其他的特点是:相对较小的值保存在左节点中,较大的值保存在右节点中,因为这个特点使查找的效率特别高。

遍历二叉查找树有三种方式:中序,先序和后序

中序:按照节点上的键值,已升序访问树中所有节点,先访问左子树,在访问根节点,最后访问右子树。
file
中序

先序:先访问根节点,然后以同样方式访问左子树和右子树
file
先序

后序:先访问叶子节点,从左子树到右子树,再到根节点
file
后序

还有两种搜索方法:深度优先搜索和广度优先搜索

深度优先搜索时从一条路径的起始顶点开始一直到最后一个顶点,然后回溯,继续追溯下一条路径,直到到达最后的顶点,如此往复,知道没有路径为止。
file
深度优先搜索

广度优先搜索是从第一个顶点开始,首先检查最靠近第一个顶点的一层,再逐渐向下移动到离起始顶点最远的一层。
file
广度优先搜索

同步创建目录

fs.accessSync是fs.access的同步方法用于检查文件是否存在,检查是否对文件是否有读写权限,当操作成功时返回值和异步方法执行成功相同,但操作失败时会抛出异常。

fs.mkdirSync是同步创建目录

话不多说,我们直接上代码

let fs = require("fs");
let path = require("path")
function mkdirSync(paths){
let arr = paths.split("/");
for(let i=0;i<arr.length;i++){
let currentPath = arr.slice(0,i+1).join("/");
try{
fs.accessSync(currentPath) //如果路径存在 不创建目录
}catch(e){
fs.mkdirSync(currentPath)
}
}
}

mkdirSync("a/b/c/d") //默认创建目录 必须父级存在 才能创建子级
异步创建目录

function mkdir(paths,cb){
let arr = paths.split("/");
function next(index){
if(index>=arr.length) return cb();
let currentPath = arr.slice(0,index+1).join("/");
fs.access(currentPath,(err)=>{
if(err){
fs.mkdir(currentPath,()=>next(index+1))
}else{ //如果存在则不创建
next(index+1)
}
})
}
next(0)
}
mkdir("a/b/c/d/e",(err)=>{
console.log("创建完成");
})

file

创建目录

深度删除目录(同步)

fs.stat() 方法用于查询文件信息,可以用于查询文件的大小、创建时间、权限等相关信息。fs.stat() 是异步方法,还有一个同步方法 fs.statSync(path)返回一个对象

思路是:一个分支上先删除儿子再删除自己,然后到另一个分支上删除儿子再删除自己。

function removeSync(dir){
let statObj = fs.statSync(dir)
if(statObj.isDirectory()){
let dirs = fs.readdirSync(dir) //返回一个数组
// console.log(dirs);
for(let i = 0;i<dirs.length;i++){
//把路径进行包装
let current =path.join(dir,dirs[i])
removeSync(current) //删除儿子节点 再将自己删除
}
fs.rmdirSync(dir) //删除自己
}else{
//文件就删除
fs.unlinkSync(dir)
}
}
removeSync("a")
广度删除目录(同步)

思路:通过while循环横向列出所有文件的路径,然后通过倒叙删除。

while(current = arr[index++]){
let statObj = fs.statSync(current);
if(statObj.isDirectory()){
let dirs =fs.readdirSync(current);
dirs = dirs.map(d=>path.join(current,d)); //当前儿子的文件夹路径
arr = [...arr,...dirs]
}
}
结果:[ 'a', 'a\b', 'a\b\c', 'a\b\c\d' ]

function wideSync(dir){
let arr = [dir];
let index = 0;
let current; //读取的当前项目
while(current = arr[index++]){
let statObj = fs.statSync(current);
if(statObj.isDirectory()){
let dirs =fs.readdirSync(current);
dirs = dirs.map(d=>path.join(current,d)); //当前儿子的文件夹路径
arr = [...arr,...dirs]
}
}
//倒叙删除
for(let i = arr.length-1;i>=0;i--){
let current = arr[i]
let statObj = fs.statSync(current);
if(statObj.isDirectory()){
fs.rmdirSync(current)
}else{
fs.unlinkSync(current)
}
}
}
wideSync("a")
深度删除目录(串行异步)

function rmdirSeries(dir,callback){
fs.stat(dir,(err,statObj)=>{
if(statObj.isDirectory()){
//读取文件内容
fs.readdir(dir,(err,dirs)=>{
dirs = dirs.map(d=>path.join(dir,d))
function next(index){
if(index == dirs.length) return fs.rmdir(dir,callback)
//先取出数组中的第一个 第一个删除后 在删第二个
rmdirSeries(dirs[index],()=>next(index+1))
}
next(0)
})
}else{
fs.unlink(dir,callback)
}
})
}
rmdirSeries("a",()=>{
console.log("删除成功");
})
深度删除目录(并行异步)

function removeDirParalle(dir,callback){
fs.stat(dir,(err,statObj)=>{
if(statObj.isDirectory()){
//读取文件内容
fs.readdir(dir,(err,dirs)=>{
if(dirs.length == 0){
return fs.rmdir(dir,callback)
}
dirs = dirs.map(d=>{
let current = path.join(dir,d);
//每个人删除之后就调用done
removeDirParalle(current,done);
return current
})
//并发删除
let index = 0;
function done(){
if(++index == dirs.length){
fs.rmdir(dir,callback)
}
}
})
}else{
fs.unlink(dir,callback)
}
})
}
removeDirParalle("a",()=>{
console.log("删除成功");
})

文章来自:https://developer.51cto.com/art/202011/631497.htm

发表评论

0/200
0 点赞
0 评论
收藏
为你推荐 换一批