NODEJS硬实战笔记(fs)

作者: 77即是正义 | 来源:发表于2017-03-12 22:35 被阅读704次

    文件系统:通过异步和同步的方法处理文件

    fs模块概述

    • fs方法(支持的POSIX文件方法):

      • fs.rename:改变文件名称
      • fs.truncate:截断或者扩展文件到指定的长度
      • fs.ftruncate:和truncate一样,但将文件描述符作为参数
      • fs.chown:改变文件的所有者以及组
      • fs.fchown:和chown一样,但不将文件描述符作为参数
      • fs.lchown:和chown一样,但不解析符号链接
      • fs.chmod:修改文件权限
      • fs.fchmod:和chomd一样,但将文件描述符作为参数
      • fs.lchomd:和chomd一样,但不解析符号链接
      • fs.state:获取文件状态
      • fs.lstat:和stat一样,但返回信息是关于符号链接而不是它指向的内容
      • fs.fstat:和stat一样,但将文件描述符作为参数
      • fs.link:创建一个硬链接
      • fs.symlink:创建一个软链接
      • fs.realpath:返回规范的绝对路径名
      • fs.readlink:读取一个软链接的值
      • fs.unlink:删除文件
      • fs.rmdir:删除文件目录
      • fs.mkdir:创建文件目录
      • fs.readdir:读取一个文件目录的内容
      • fs.close:关闭一个文件描述符
      • fs.open:打开或者创建一个文件用来读取或者写入
      • fs.utimes:设置文件的读取和修改时间
      • fs.futimes:和utimes一样,但将文件描述符作为参数
      • fs.fsync:同步磁盘中的文件数据
      • fs.write:写入数据到一个文件
      • fs.read:读取一个文件的数据
      • <font color=grey>文件描述符:文件的索引
      • 符号链接:又叫软链接,是一类特殊的文件,这个文件包含了另一个文件的路径名(绝对路径或者相对路径)</font>
    • fs操作策略:

      • 流:通过fs.createReadStream和fs.createWriteStream以及pipe连接进行流操作
      • 批量文件操作:通过fs.readFile等方法进行文件的一次性加载到内存或者一次性写入文件,操作后保存在一个buffer对象当中
    • 文件监视:

      • fs.watch:
        • 特点:一个更可靠的实现使得文件改变的事件能够总是被执行,一个更快的实现,当事件发生时能够立即通知到Node进程。
        • 监测文件修改,这个方法是通过监听操作系统提供的各种“事件”(内核发布的消息)实现的。(在Mac上行为不正常)
      • fs.watchFile:
        • 在监听一个目录时,许多对文件的更新不会被fs.watchFile监听到。如果你想使用fs.watchFile,那么可以监听单个文件
        • 返回的值中会包含两个fs.Stats对象来表示文件当前和过去的状态
        • 轮询监测(时间参数可调,但是如果监测的文件过多的话内存吃不消)
    • 同步的替代方案:

      • 一般在异步方法的后面添加Sync即为该方法的同步方法
      • 同步方法会阻塞你的单线程Node进程直到它结束,所以一般而言同步方法应该在第一次初始化的时候使用,而不能再回调中使用。
    • 递归文件

      • 同步递归:

        • 因为是同步方法,可以在处理函数外面用try,catch来获取捕捉异常,非常的方便。
      • 异步递归:

        • 使用计数器来统计所以异步方法是否全部完成。在异步方法开始之前累加计数器,在回调开始之前减去计数器。
        • 使用错误处理句柄来处理异常,用来确保如果有多个错误,但是回调只会执行一次。
        var errored = false;
        
        function error(err) {
            if (!errored) cb(err);
            errored = true;
        }
        
      • 性能分析:

        • 同步的方法比较快,因为同步的方法不会延迟执行,就算相对的异步方法执行很快。当CPU准备妥当时,同步方法会立即执行,会保证你只需要等待必要的I/O完成。但是同步方法在等待运行的期间会阻塞其他事情的发生。
    • 文件锁

      • node进行文件咨询锁的思想是创建利用锁文件:
        • 使用独占标记创建锁文件

          • fs模块为所有需要打开文件的方法提供了一个x标记。这告诉操作系统这个文件应该以独占模式打开(O_EXCL)。当使用这个方法时,若这个文件存在,文件不能被打开。
          fs.open('config.lock', 'wx', function(err)) {
              if (err) return console.err(err);
          })
          
        • 使用mkdir创建锁文件

          • 当锁文件在网络磁盘上时独占模式可能不能正常工作,因为一些系统在网络磁盘上并不识别O_EXCL标记。当目录已经存在时mkdir方法会失败。
    • 文件数据库

      • 策略是不断的追加记录,在处理的时候不断的覆盖原始记录。
      var fs = require('fs')
      var EventEmitter = require('events').EventEmitter
      
      var Database = function(path) {
          this.path = path
          
          // 数据库key/value映射表
          this._records = Object.create(null);
          this._writeStream = fs.createWriteStream(this.path, {
              encoding: 'utf8',
              flags: 'a'
          })
          
          this._load()
      }
      
      // 继承自EventEmitter,让它有可以监听事件、传递事件的功能
      Database.prototype = Object.create(EventEmitter.prototype)
      
      Database.prototype._load = function() {
          var stream = fs.createReadStream(this.path, { encoding: 'utf8' });
          var database = this;
          
          var data = '';
          // 当输入流准备好时触发
          stream.on('readable', function() {
              data += stream.read();
              // 每一行是一组数据
              var records = data.split('\n');
              // 这里存在一点疑问,书上的解释是获取最后一个可能未完成的记录(但是不是会把它从数组中删除吗?)
              data = records.pop();
              
              for (var i = 0; i < records.length; i++) {
                  try {
                      var record = JSON.parse(records[i]);
                      if (record.value == null) {
                          delete database._records[record.key];
                      } else {
                          database._records[record.key] = record.value;
                      }
                  } catch(e) {
                      database.emit('error', 'found invalid record:', records[i]);
                  }
              }
          });
          
          // 流处理完后发送load事件给消费者
          stream.on('end', function() {
              database.emit('load');
          })
      }
      

    相关文章

      网友评论

        本文标题:NODEJS硬实战笔记(fs)

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