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:读取一个文件的数据
    • <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');
        })
    }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容

  • 文件系统模块是一个封装了标准的 POSIX 文件 I/O 操作的集合。通过require('fs')使用这个模块。...
    保川阅读 783评论 0 0
  • Node.js 常用工具 util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScr...
    FTOLsXD阅读 535评论 0 2
  • https://nodejs.org/api/documentation.html 工具模块 Assert 测试 ...
    KeKeMars阅读 6,332评论 0 6
  • 个人入门学习用笔记、不过多作为参考依据。如有错误欢迎斧正 目录 简书好像不支持锚点、复制搜索(反正也是写给我自己看...
    kirito_song阅读 2,472评论 1 37
  • 模块化公布自己的模块功能. 其他模块调用另外的模块. 公布方法 如果要输出一个键值对象{},可以利用exports...
    httIsHere阅读 522评论 0 0