详解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学习笔记之网络编程
Aug 03 NodeJs
Nodejs的express使用教程
Nov 23 NodeJs
深入浅析NodeJs并发异步的回调处理
Dec 21 NodeJs
利用nodejs监控文件变化并使用sftp上传到服务器
Feb 18 NodeJs
详解nodeJS中读写文件方法的区别
Mar 06 NodeJs
手把手教你把nodejs部署到linux上跑出hello world
Jun 19 NodeJs
nodejs结合Socket.IO实现的即时通讯功能详解
Jan 12 NodeJs
nodejs实现解析xml字符串为对象的方法示例
Mar 14 NodeJs
详解NodeJS Https HSM双向认证实现
Mar 12 NodeJs
Nodejs 识别图片类型的方法
Aug 15 NodeJs
linux 下以二进制的方式安装 nodejs
Feb 12 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
DSP接收机前端设想
2021/03/02 无线电
给海燕B411配件机起死回生配上件
2021/03/02 无线电
PHP 字符串分割和比较
2009/10/06 PHP
php下载excel无法打开的解决方法
2013/12/24 PHP
浅谈laravel框架与thinkPHP框架的区别
2019/10/23 PHP
表单提交验证类
2006/07/14 Javascript
一个js封装的不错的选项卡效果代码
2008/02/15 Javascript
javascript模版引擎-tmpl的bug修复与性能优化分析
2011/10/23 Javascript
JavaScript 学习笔记之一jQuery写法图片等比缩放以及预加载
2012/06/28 Javascript
详细介绍8款超实用JavaScript框架
2013/10/25 Javascript
JS连连看源码完美注释版(推荐)
2013/12/09 Javascript
js 动态修改css文件的方法
2014/08/05 Javascript
使用node.js半年来总结的 10 条经验
2014/08/18 Javascript
JavaScript通过select动态更换图片的方法
2015/03/23 Javascript
深入理解JavaScript中的箭头函数
2015/07/28 Javascript
jQuery解决$符号命名冲突
2016/06/18 Javascript
vue.js-div滚动条隐藏但有滚动效果的实现方法
2018/03/03 Javascript
巧妙运用v-model实现父子组件传值的方法示例
2019/04/07 Javascript
图解NodeJS实现登录注册功能
2019/09/16 NodeJs
[04:39]显微镜下的DOTA2第十三期—Pis卡尔个人秀
2014/04/04 DOTA
基于python实现名片管理系统
2018/11/30 Python
对python多线程SSH登录并发脚本详解
2019/02/14 Python
python opencv对图像进行旋转且不裁剪图片的实现方法
2019/07/09 Python
python自定义时钟类、定时任务类
2021/02/22 Python
Python configparser模块配置文件过程解析
2020/03/03 Python
python使用gdal对shp读取,新建和更新的实例
2020/03/10 Python
linux mint中搜狗输入法导致pycharm卡死的问题
2020/10/28 Python
Linux内核产生并发的原因
2012/07/13 面试题
求职信的七个关键技巧
2014/02/05 职场文书
不拖欠农民工工资承诺书
2014/03/31 职场文书
机械加工与数控专业自荐书
2014/06/04 职场文书
2013年最新自荐信范文
2014/06/23 职场文书
美术专业自荐信
2014/07/07 职场文书
个人德育工作总结
2015/03/05 职场文书
nginx location中多个if里面proxy_pass的方法
2021/03/31 Servers
PHP判断是否是json字符串
2021/04/01 PHP