详解nodejs 文本操作模块-fs模块(一)


Posted in NodeJs onDecember 22, 2016

JS的安全性问题,就决定了JS想要取操作数据库操作文件是不可实现的,而Nodejs作为服务端的JS,如果依然不能操作文件,那么又如何称之为服务端语言呢,所以在Nodejs中,提供了一个fs(File System)模块,以实现文件及目录的读写操作。

写在前面

Nodejs的一大优势就在于,支持异步调用,不管是在读取数据库,还是在读取文件时,都可以使用异步的方式进行处理,这样就可以处理高并发的情况,从本篇开始,开始对Nodejs的fs模块中,一些重要的API,结合源码,进行一些说明学习。

fs模块支持的属性和方法

fs模块是一个很重要的模块,也支持非常多的属性和方法,可以直接在nodejs中查看,fs模块支持的属性,创建一个app.js文件,输入以下代码,运行即可。

var fs = require("fs"), 
 i; 
  
for(i in fs){ 
 console.log(i); 
}

由于fs的家族子弟太多,这里就不一一列举了,下面就开始介绍一下fs家族的核心子弟。

1:open和openSync方法

对于文件操作,最基本的莫过于打开文件,你想要读写文件,那么就必须要打开文件才能读写,就像你要往冰箱放东西或者从冰箱拿东西,那么你首先要打开冰箱才行。

所以,这里就以文件的打开为首个属性,来进入文件模块。

文件操作中,分为同步操作和异步操作,它们的命名规则都是相同的,比如这里,open方法是异步方法,同步的方法是在异步方法的基础上,添加一个”Sync“的后缀,也就是这里的openSync,还有读取文件时也是,readFile和readFileSync等,这个在后面不再多说,并且它们的使用基本上也是相同的,唯一的差距在于异步的数据是以第二个参数的形式传入回调函数,而同步的方法,返回值就是处理的结果数据。

下面,就会以open和openSync为基础,把这些都说明一下。

open和openSync的使用方法:

var fs = require("fs"); 
 
fs.open(filename,flags,[mode],callback); 
 
//同步打开文件 
var fs = openSync(filename,flags,[mode]);

以open方法的使用方式为例,open方法中,可以使用4个参数,其中filename参数,flags参数,callback参数是必须指定的参数,mode参数为可选参数。

其中:

filename是你所要读取文件的路径,可以是绝对路径,也可以是相对路径,这个就看你喜好了。

callback为打开文件成功后,执行的回调函数,回调函数的格式为:

function(err , data){ 
//err为读取文件失败时,触发的错误对象 
//data为回调函数的可用数据。 
//在open的回调函数中,data是一个整数值,代表打开文件时返回的文件描述符(文件句柄)。 
//每一个文件,都有唯一的文件描述符(句柄)。 
}

基本上,在fs模块中的所有异步执行函数的回调函数,都是这样的格式,唯一的差距就是在于回调函数的第二个数据,也就是操作成功后,得到的数据的差别,在以后的内容中,对该部分,就不再多说。

mode为可选参数,用于指定当文件被打开时,对该文件的读写权限,默认值为0666(可读写),该方法使用4个数字组成mode属性值,它们的组成方式符合以下规则:

第一个数字必须是0,表示该数据是一个八进制的数字。

第二个数字,用于规定文件或者目录所有者的权限。

第三个数字,用于规定文件或者目录所有者所属用户组的权限。

第四个数字,规定其他人的权限。

对于上述的第二,第三,第四个数字,读写权限的设置符合以下规则。

设置为1:表示为执行权限。

设置为2:表示有写权限。

设置为4:表示有毒权限。

如果需要设置有执行权限和写权限,则数字设置为3,如果只想要有读写权限,则设置为6,即,你想要哪些权限,你就把上述代表权限的数字相加即可。如果设置,需要执行权限,读写权限,则可以设置为7,默认状态为设置为6,即拥有读写权限。
open方法支持的另外一个参数flags,表示该对象,可以对文件执行哪些操作,支持的属性过多,所以放到一个列表中了:

属性 意义
r 以【只读】的方式打开文件. 当文件不存在时产生异常
r+ 以【读写】的方式打开文件. 当文件不存在时产生异常
rs 同步模式下,以【只读】的方式打开文件. 指令绕过操作系统的本地文件系统缓存。该功能主要用于打开 NFS 挂载的文件, 因为它可以让你跳过默认使用的过时本地缓存. 但这实际上非常影响 I/O 操作的性能, 因此除非你确实有这样的需求, 否则请不要使用该标志。注意: 这并不意味着 fs.open() 变成了一个同步阻塞的请求. 如果你想要一个同步阻塞的请求你应该使用 fs.openSync()。
rs 同步模式下,以【只读】的方式打开文件. 指令绕过操作系统的本地文件系统缓存。该功能主要用于打开 NFS 挂载的文件, 因为它可以让你跳过默认使用的过时本地缓存. 但这实际上非常影响 I/O 操作的性能, 因此除非你确实有这样的需求, 否则请不要使用该标志。注意: 这并不意味着 fs.open() 变成了一个同步阻塞的请求. 如果你想要一个同步阻塞的请求你应该使用 fs.openSync()。
rs+ 同步模式下, 以【读写】的方式打开文件. 请谨慎使用该方式, 详细请查看 ‘rs' 的注释.
w 以【只写】的形式打开文件. 文件会被创建 (如果文件不存在) 或者覆盖 (如果存在).
wx 作用与”w”类似,区别是如果文件存在则操作会失败(必须去创建一个新的文件才行)
w+ 以【读写】的方式打开文件. 文件会被创建 (如果文件不存在) 或者覆盖 (如果存在).
wx+ 作用与”w+”类似,区别是如果文件存在则操作会失败(必须去创建一个新的文件才行)
a 以【附加】的形式打开文件,即新写入的数据会附加在原来的文件内容之后. 如果文件不存在则会默认创建.
ax 作用与”a”类似,区别是如果文件存在则操作会失败(必须去创建一个新的文件才行)
a+ 以【读取】和【附加】的形式打开文件. 如果文件不存在则会默认创建.
ax+ 作用与”a+”类型,区别是如果文件存在则操作会失败(必须去创建一个新的文件才行

关于open的官方说明,请参考:fs.open()

到这里为止,使用open方法时的一些属性,就说完了,接下来看下如何使用的,这里只给一个最简单的例子,因为open只是单纯的打开文件,并不会执行其他的操作,当然如果”w/w+“模式的话,会把文件清空。但是,open的功能,也只是最单纯的打开文件而已,所以这里只给一个最简单的例子,至于其他的一些复杂的操作,在后面,会慢慢涉及到的。

var fs = require("fs"), 
 i; 
  
fs.open("fs.txt","r+",function(err,fd){ 
 console.log(err); 
 console.log(fd); 
 //open一个文件成之后,返回的是一个文件的描述符,是一个数字 
});

这里就不在添加openSync的示例了,当然,这里也可以按照自己的意愿修改第二个参数(flags)和第三个参数(mode)的值,不过,对于open,修改这些并没有任何意义,只对打开文件之后的操作,有影响,所以这里不再添加示例。

看下源码中,关于open方法的实现:

var binding = process.binding('fs'), 
 FSReqWrap = binding.FSReqWrap; 
//binding是C++与nodejs的接口, 
//FSReqWrap是C++实现的一个方法。具体完成什么功能,不知 
  
function modeNum(m, def) { 
 //验证mode所用的,把m转换成数字 
 //如果是数字,则直接返回, 
 //如果是字符串,则转换成8禁止数字, 
 //如果第二个参数存在,则把第二个参数转换为数字, 
 //如果不存在,则返回undefined 
 if (util.isNumber(m)) 
 return m; 
 if (util.isString(m)) 
 return parseInt(m, 8); 
 if (def) 
 return modeNum(def); 
 return undefined; 
} 
 
function makeCallback(cb) { 
 
 if (util.isNullOrUndefined(cb)) { 
 //如果传入的值为null或者undefined,则返回异常处理函数 
 return rethrow(); 
 //rethrow是一个异常处理函数,这里不涉及 
 } 
 
 if (!util.isFunction(cb)) { 
 //如果传入的值,不是function类型,则抛出一个类型错误 
 throw new TypeError('callback must be a function'); 
 } 
 
 //否则,形成一个闭包,用于改变回调函数的内部指向 
 //当该诶不上下文时,则内部的this指向顶级作用域 
 return function() { 
 return cb.apply(null, arguments); 
 }; 
} 
 
function nullCheck(path, callback) { 
 //判断path是否合法,就是不能再path中,包含空格符。 
 if (('' + path).indexOf('\u0000') !== -1) { 
 var er = new Error('Path must be a string without null bytes.'); 
 if (!callback) 
  throw er; 
 //如果不合法,则传入err,并执行回调函数 
 process.nextTick(function() { 
  callback(er); 
 }); 
 return false; 
 } 
 return true; 
} 
  
fs.open = function(path, flags, mode, callback) { 
 //使用传入的最后一个参数,生成一个有闭包的函数,作为回调函数 
 callback = makeCallback(arguments[arguments.length - 1]); 
 mode = modeNum(mode, 438 /*=0666*/); 
 //设置mode为八进制的数值,如果没有设置,则默认设置为438,八进制=0666 
 
 //如果path路径不合法,则直接执行回调,并把错误对象传入回调函数, 
 //结束 
 if (!nullCheck(path, callback)) return; 
 
 //否则,实例化一个FSReqWrap对象,并给该对象绑定一个oncomplete方法。 
 var req = new FSReqWrap(); 
 req.oncomplete = callback; 
 
 //使用C++公开的接口,执行打开文件的操作。 
 binding.open(pathModule._makeLong(path), 
    stringToFlags(flags), 
    mode, 
    req); 
};

以上源码中的binding,包含了一些直接调用C++程序的接口,这里不涉及该部分,如果想要了解,请查看:Nodejs如何与C++对接的。

2:close和closeSync方法

前面说了open方法,可以打开文件,那么就必然有方法来关闭文件,所以这里看看fs模块中模块的关闭。

使用方法:

var fs = require("fs"); 
 
fs.open("fs.txt","r",function(err,fd){ 
 //有一点需要注意,close文件时,需要文件描述符,也就是open成功时,返回的数字。 
 //即,需要fd。 
  
 fs.close(fd,function(err){ 
  //close的回调函数,该回调只支持一个参数,就是当发生错误时的错误对象 
 }); 
 //关于close的同步执行方法closeSync,这里就不举例了 
});

象征性的看下,close源码中的处理:

fs.close = function(fd, callback) { 
 var req = new FSReqWrap(); 
 req.oncomplete = makeCallback(callback); 
 //创建一个实例,并把回调函数,绑定到实例中的oncomplete属性上 
 
 //调用C++中的close方法。 
 binding.close(fd, req); 
};

篇幅有限,本篇就到此为止。

总结

本篇虽然只说了这最基本的四种方法,但是也是把fs模块中一些基本的方法,都包含了,比如flag属性,比如mode属性,比如回调方法的参数,比如异步和同步的命名规范等,所以这一篇文章也是属于很重要的一篇。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs教程之制作一个简单的文章发布系统
Nov 21 NodeJs
NodeJS中Buffer模块详解
Jan 07 NodeJs
nodejs加密Crypto的实例代码
Jul 07 NodeJs
学习 NodeJS 第八天:Socket 通讯实例
Dec 21 NodeJs
深入理解Nodejs Global 模块
Jun 03 NodeJs
Nodejs实现文件上传的示例代码
Sep 26 NodeJs
nodejs实现连接mongodb数据库的方法示例
Mar 15 NodeJs
基于nodejs res.end和res.send的区别
May 14 NodeJs
Nodejs异步流程框架async的方法
Jun 07 NodeJs
nodejs如何在package.json中设置多条启动命令
Mar 16 NodeJs
nodejs+express最简易的连接数据库的方法
Dec 23 NodeJs
浅谈JS和Nodejs中的事件驱动
May 05 NodeJs
详解nodejs 文本操作模块-fs模块(二)
Dec 22 #NodeJs
学习 NodeJS 第八天:Socket 通讯实例
Dec 21 #NodeJs
详解Nodejs基于mongoose模块的增删改查的操作
Dec 21 #NodeJs
nodejs redis 发布订阅机制封装实现方法及实例代码
Dec 15 #NodeJs
解析NodeJs的调试方法
Dec 11 #NodeJs
nodejs连接mongodb数据库实现增删改查
Dec 01 #NodeJs
Nodejs 搭建简单的Web服务器详解及实例
Nov 30 #NodeJs
You might like
PHP技术开发技巧分享
2010/03/23 PHP
php实现中文字符截取防乱码方法汇总
2015/04/29 PHP
php单一接口的实现方法
2015/06/20 PHP
简单的php+mysql聊天室实现方法(附源码)
2016/01/05 PHP
PHP正则表达式处理函数(PCRE 函数)实例小结
2019/05/09 PHP
解决 firefox 不支持 document.all的方法
2007/03/12 Javascript
LazyForm jQuery plugin 定制您的CheckBox Radio和Select
2009/10/24 Javascript
利用jquery操作Radio方法小结
2014/10/20 Javascript
Nodejs全栈框架StrongLoop推荐
2014/11/09 NodeJs
推荐6款基于jQuery实现图片效果插件
2014/12/07 Javascript
javascript中不易分清的slice,splice和split三个函数
2016/03/29 Javascript
AngularJS动态绑定HTML的方法分析
2016/11/07 Javascript
微信小程序开发(一) 微信登录流程详解
2017/01/11 Javascript
最全的JavaScript开发工具列表 总有一款适合你
2017/06/29 Javascript
mescroll.js上拉加载下拉刷新组件使用详解
2017/11/13 Javascript
jQuery md5加密插件jQuery.md5.js用法示例
2018/08/24 jQuery
JS实现带阴历的日历功能详解
2019/01/24 Javascript
教你如何在Django 1.6中正确使用 Signal
2014/06/22 Python
python实现的用于搜索文件并进行内容替换的类实例
2015/06/28 Python
Python中死锁的形成示例及死锁情况的防止
2016/06/14 Python
谈谈如何手动释放Python的内存
2016/12/17 Python
Python md5与sha1加密算法用法分析
2017/07/14 Python
Python基于回溯法子集树模板解决马踏棋盘问题示例
2017/09/11 Python
Python迭代器模块itertools使用原理解析
2019/12/11 Python
python3用urllib抓取贴吧邮箱和QQ实例
2020/03/10 Python
PyQt5+Pycharm安装和配置图文教程详解
2020/03/24 Python
Django ForeignKey与数据库的FOREIGN KEY约束详解
2020/05/20 Python
SQL Server 2000数据库的文件有哪些,分别进行描述
2013/03/30 面试题
国税会议欢迎词
2014/01/16 职场文书
2014年社区宣传工作总结
2014/12/02 职场文书
个人简历自我评价怎么写
2015/03/10 职场文书
水电施工员岗位职责
2015/04/11 职场文书
学校教师师德师风承诺书
2015/04/28 职场文书
二婚主持词
2015/06/30 职场文书
公司开业的祝贺语大全(60条)
2019/07/05 职场文书
标准版个人借条怎么写?以及什么是借条?
2019/08/28 职场文书