NODEJS硬实战笔记(fs)

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

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:读取一个文件的数据
    • 文件描述符:文件的索引
    • 符号链接:又叫软链接,是一类特殊的文件,这个文件包含了另一个文件的路径名(绝对路径或者相对路径)
  • 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))