美文网首页
Node文件系统

Node文件系统

作者: 郝翔 | 来源:发表于2016-07-02 12:07 被阅读57次

    Node 通过封装基本的POSIX函数来提供文件系统,使用require('fs')来使用这个模块,所有与文件相关的方法,都提供了异步和同步的形式。 异步的方法通常会将一个可选的回调函数作为最后一个参数,回调函数的第一个参数通常留给意外情况,如果操作是成功的,第一个参数将是null或者undeefined。 使用同步方法,对于任何意外都会即时抛出,可以使用try/catch语句来处理意外情况,或者让错误时间向上冒泡。 下面是一个有关异步方法的基本例子:

    const fs = require('fs');
    fs.unlink('/tmp/hello', (err) => {
      if (err) throw err;
      console.log('sucessfully deleted /tmp/hello');
    }
    

    再跟着一个同步的例子:

    const fs = require('fs');
    fs.unlink('/tmp/hello');
    console.log('successfully deleted /tmp/hello');
    

    使用异步方法时,需要注意异步方法的执行不一定按照书写顺序,比如下面这种写法很容易出错:

    fs.rename('/tmp/hello', '/tmp/world', (err) => {
       if (err) throw err;
       console.log('renamed compelte');
    });
    
    fs.stat('/tmp/world', (err, stats) => {if (err) throw err;
    console.log(`stats: ${JSON.stringify(stats)}`)});
    

    在这里,很可能fs.stat函数先于fs.rename,这样会出现一些不必要的错误,正确的方法应该是写在回调函数中。

    fs.rename('/tmp/hello/', '/tmp/world', (err) ss=> {
        if (err) throw err;
        fs.stat('/tmp/world'),(err, stats) => {
            console.log(`stats: ${JSON.stringfy(stats)});
        });
    });
    

    执行复杂耗时的方法,强烈建议使用异步版本,同步方法在它们执行结束之前,会一直锁住当前线程,阻断所有操作。 在fs模块中,可以使用相对路径,但是需要留意参照的路径来自于process.cwd()的返回值。 很多fs函数可以忽略掉回调参数,如果这样进行使用,默认会抛出错误,为了跟踪到函数调用的位置,可以设置NODE_DEBUG环境变量:

    $ cat script.js
    function bad() {
      require('fs').readFile('/');ssss
    }
    bad();
    
    $ env NODE_DEBUG=fs node script.js
    fs.js:66
            throw err;
                  ^
    Error: EISDIR, read
        at rethrow (fs.js:61:21)
        at maybeCallback (fs.js:79:42)
        at Object.fs.readFile (fs.js:153:18)
        at bad (/path/to/script.js:2:17)
        at Object.<anonymous> (/path/to/script.js:5:1)
        <etc.>
    

    fs.watch(filename[, options][, listener]) 监听制定文件或者目录的变化情况,filename参数可以是文件或者目录,这个方法返回一个fs.FSWather对象。 第二个参数是可选的,提供的options参数应该是一个对象,里面要求的成员是persistentrecursive,这个两个成员都是布尔类型的值。 用做监听的回调函数有两个参数,分别是(event, filename)event的值视情况,返回字符串changerename,文件名指的是触发事件的这个文件。看下面的这个例子:

    // node.md
    // 被监听的文件
    this is cat.
    
    // app.js
    // 用来监听文件改变
        fs.watch('./node.md', (event, filename) => {
            console.log('下面是event参数,event参数的类型,filename');
            console.log(typeof event);
            console.log(filename);
        });
    
    // node.md
    // 这里修改了监听的node.md文件
    this is dog.
    
    // console
    // 执行结果
    下面是event参数,event参数的类型,filename
    change
    string
    node.md
    
    // node.md => node1.md
    // 修改文件的名字
    
    // console
    // 执行结果
    下面是event参数,event参数的类型,filename
    rename
    string
    node1.md
    

    注意事项: fs.watch并不是跨所有平台的,在某些常见下不一定可用。 第二个参数中的布尔值recursive只在osx和window下可以使用。

    可用性:

    • fs.watch依赖于操作系统底层模块,由操作系统底层模块通知Node文件的变化。

    • 如果某个操作系统底层模块对于文件的监听本身就有问题,那么fs.watch是无法发挥作用的,比如监听了一些不可靠的目录和文件,网络文件系统,虚拟机系统中的文件。

    • 在linux,osx系统中,fs.watch解析路径成一个索引节点,并且监听这个节点,但是如果监听的节点被删除或者重新创建,那么此时它就成了一个新节点了,watch将会发送一个delete事件,但是仍然监听原来的节点,原来的事件不会响应新节点的改变,这种处理是符合预期的。

    • filename参数只支持在linux和windows上面指定(osx也可以,但是有些情况可能会有异常),事实上,即便是在可以使用的平台上,也不建议直接使用这个参数,因为在回调函数内部,建议增加一些逻辑判断,看一下filename是否为null,如下面的例子:

      fs.watch('somedir', (event, filename) => {
          console.log(`event is: ${event}`);
          if (filename) {
               console.log(`filename provided: ${filename}`);
           } else {
               console.log('filename not provided');
           }
      });
      

    相关文章

      网友评论

          本文标题:Node文件系统

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