zoukankan      html  css  js  c++  java
  • Node 之fs模块 运用

     fs.stat 检测是文件还是目录     fs.mkdir 创建目录      fs.writeFile 创建写入文件 * 
     fs.appendFile 追加文件        fs.readFile 读取文件     fs.readdir 读取目录 
     fs.rename 重命名          fs.rmdir 删除目录     fs.unlink 删除文件

    一、实用小Demo

     1.图片上传

    // 1. 判断服务器上面有没有 upload 目录,没有就创建这个目录
    // 2. 找出 html 目录下面的所有的目录,然后打印出来
    
    const fs = require('fs');
    fs.stat('upload', (err, stats) => {
      // 判断有没有 upload 目录
      if(err) {
        // 如果没有
        fs.mkdir('upload', (error) => {
          if(error) {
            console.log(error);
            return false;
          } else {
            console.log("创建 upload 目录成功!");
          }
        })
      } else {
        // 如果有
        console.log(stats.isDirectory());
        console.log("有 upload 目录,你可以做更多操作!");
      }
    })
    

     2.读取目录全部文件

    const fs = require('fs');
    fs.readdir('node_modules', (err, files) => {
      if(err) {
        console.log(err);
        return false;
      } else {
        // 判断是目录还是文件夹
        console.log(files);
    
        let filesArr = [];
    
        (function getFile(i) {
          
          // 循环结束
          if(i == files.length) {
            // 打印出所有目录
            console.log("目录:");
            console.log(filesArr);
            return false;
          }
    
          // 判断目录是文件还是文件夹
          fs.stat('node_modules/' + files[i], (error, stats) => {
    
            if(stats.isDirectory()) {
              filesArr.push(files[i]);
            }
    
            // 递归调用
            getFile(i+1);
            
          })
        })(0)
      }
    })
    

      

    二、实现递归创建目录

      我们创建一个函数,参数为一个路径,按照路径一级一级的创建文件夹目录。

     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 的实现

    上面两种方式,同步阻塞代码,性能不好,异步回调函数嵌套性能好,但是维护性差,我们想要具备性能好,代码可读性又好可以使用现在 NodeJS 中正流行的 async/await 的方式进行异步编程,想了解 async/await 可以看 异步发展流程 —— 异步编程的终极大招 async/await 这篇文章。

    使用 async 函数中 await 等待的异步操作必须转换成 Promise,以前我们都使用 util 模块下的 promisify 方法进行转换,其实 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 的写法,代码更像同步的实现方式,却是异步执行,所以同时兼顾了性能和代码的可读性,优势显而易见,在使用 NodeJS 框架 Koa 2.x 版本时大量使用这种方式进行异步编程。

  • 相关阅读:
    字符个数统计
    面试题——字符的左右移动
    5. Longest Palindromic Substring
    Linux- AWS之EC2大数据集群定时开关机
    Openldap- 大机群身份验证服务
    Linux- 自动备份MySQL数据库脚本
    Linux- 运维
    JAVA- 切换默认的Java
    HIVE- 新建UDF范例
    Hadoop- 集群启动详解
  • 原文地址:https://www.cnblogs.com/Jiangchuanwei/p/10236214.html
Copyright © 2011-2022 走看看