目录树 删除 数据结构_Node.JavaScript文件系统中目录的操作

作者:小丑 来源:前端简报

c5748c1d65f78665c1614bbd0bc0d1d4.png

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

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

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

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

61aa3a35bbc92dd4efabdad8dffff59b.png

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

4e5085a3fdc18c16e9680055fd524c4b.png

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

3a7156002245ef47b302dec63c3ee521.png

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

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

bd282b68347486079374c8d6e79cba23.png

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

034b5bca01f96cb5cf14d36146a44da7.png

同步创建目录

_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

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("创建完成");

})

f7b073c24bbbe11317dda0d9973730ab.png

深度删除目录(同步)

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

//把路径进行包装

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', 'ab', 'abc', 'abcd' ]

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("删除成功");

})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值