美文网首页node专题
node文件目录操作之遍历删除目录

node文件目录操作之遍历删除目录

作者: Mstian | 来源:发表于2020-10-29 14:43 被阅读0次

    从node目录删除学习深度优先遍历和广度优先遍历处理任务思想。
    使用到的模块:fs path

    使用到的方法:(均为同步方法)
    let statObj = fs.statSync(path):判断是文件夹还是文件 statObj.isDirectory() statObj.isFile()

    fs.readdirSync(dir):返回值是一个数组,用来获取当前目录下的子目录或者文件。

    fs.rmdirSync(dir):删除文件夹,注意:只能删除空文件夹,不能删除含有内容的文件夹,因此删除文件夹采用先删除子文件及子目录再删除父级文件目录。

    fs.unlinkSync(dir):删除文件
    path.join(path1,path2):将所有path片段拼接在一起,生成规范目录。

    深度优先删除目录

    思路:如下图所示结构,深度优先遍历思路就是从根节点A触发,找到B之后,继续沿着B往下找,找到E继续沿着E往下找,发现E没有子节点,那么就将E删除,接着删除F,再删除B,再去找C及其子节点,然后是D及其子节点。


    深度优先遍历
    function rmDirDeepSync(dir) {
        let statObj = fs.statSync(dir);
        if (statObj.isDirectory()) {
            let dirs = fs.readdirSync(dir);
            for(let i = 0; i < dirs.length; i++ ) {
                rmDirDeepSync(path.join(dir, dirs[i]))
            }
            fs.rmdirSync(dir);
        } else {    
            fs.unlinkSync(dir);
        }
    }
    
    rmDirDeepSync('A');
    

    广度优先删除目录

    思路:如下图所示结构,广度优先遍历的思路是使用一个数组按照顺序存储所有的节点,然后使用一个指针,依次向后挪动,指针所指向的是目录的话,再次遍历出子节点,并拼接至数组。然后从后到前依次删除。
    比如下图在数组中最终是这个样子的[ 'A', 'A/B', 'A/C', 'A/D', 'A/B/E', 'A/B/F' ]。

    广度优先遍历
    function rmDirWideSync(dir){
        let arr = [dir]; // 存储数组
        let index = 0; // 指针
        let current; // 当前指针指向的元素
        while(current = arr[index]) {
            let statObj = fs.statSync(current);
            if(statObj.isDirectory()){
                let dirArr = fs.readdirSync(current).map(d => path.join(current, d));
                arr = [...arr, ...dirArr];
            }
            index++;
        }
        for (let i = arr.length - 1; i >=0; i--) { // 倒序删除,先删除子级,再删除父级
            let statObj = fs.statSync(arr[i]);
            if(statObj.isDirectory()) {
                fs.rmdirSync(arr[i]);
            } else {
                fs.unlinkSync(arr[i]);
            }
        }
    }
    rmDirWideSync('A');
    

    总结:同步删除有广度优先和深度优先两种方案,异步删除也有两种方案,异步串行删除,和异步并行删除。

    异步串行:(采用深度递归,深度优先方案)

    function rmDirAsyncSerie(dir,cb) {
        fs.stat(dir, (err, stats) => { 
            if(stats.isDirectory()) {
                fs.readdir(dir, (err, dirs) => {
                    dirs = dirs.map((item) => {
                        return path.resolve(dir, item);
                    })
                    function next(index) {
                        if(index === dirs.length) {
                            fs.rmdir(dir, cb);
                            return;
                        }
                        rmDirAsyncSerie(dirs[index], () => {
                            next(++index);
                        });
                    }
                    next(0);
                })
            } else {
                fs.unlink(dir, cb);
            }
        });
    }
    rmDirAsyncSerie('a', () => {
      console.log('删除完成');
    });
    

    异步并行:异步的好处就是任务可以并行执行。

    function rmDirAsyncParalle(dir, cb) {
        fs.stat(dir, (err, stats) => {
            if(stats.isDirectory()) {
                fs.readdir(dir, (err, dirs) => {
                    if (dirs.length === 0) {
                        fs.rmdir(dir, cb);
                        return;
                    }
                    dirs.map((d) =>{
                        let current = path.join(dir, d);
                        rmDirAsyncParalle(current, done);
                    })
                    let index = 0;
                    function done() {
                        index++;
                        if(index === dirs.length) {
                            fs.rmdir(dir, cb);
                        }
                    }
                })
            }else{
                fs.unlink(dir, cb);
            }
        })
    }
    
    rmDirAsyncParalle('a', () => {
        console.log('删除成功');
    })
    

    并行删除效率会更高,并行和串行的区别就在于,并行是在循环中执行删除方法的,串行是执行完本次删除任务后,再去调用下一个删除方法的。

    注意观察串行删除的next方法和并行删除的done方法。

    相关文章

      网友评论

        本文标题:node文件目录操作之遍历删除目录

        本文链接:https://www.haomeiwen.com/subject/qpikvktx.html