详解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实现PHP的print_r函数代码
Mar 14 NodeJs
Nodejs使用mysql模块之获得更新和删除影响的行数的方法
Mar 18 NodeJs
Nodejs进阶:如何将图片转成datauri嵌入到网页中去实例
Nov 21 NodeJs
nodejs和php实现图片访问实时处理
Jan 05 NodeJs
nodejs中使用HTTP分块响应和定时器示例代码
Mar 19 NodeJs
使用Nodejs连接mongodb数据库的实现代码
Aug 21 NodeJs
nodejs发送http请求时遇到404长时间未响应的解决方法
Dec 10 NodeJs
nodejs基于mssql模块连接sqlserver数据库的简单封装操作示例
Jan 05 NodeJs
NodeJS搭建HTTP服务器的实现步骤
Oct 12 NodeJs
详解NodeJS Https HSM双向认证实现
Mar 12 NodeJs
NodeJS http模块用法示例【创建web服务器/客户端】
Nov 05 NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 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随机数生成代码与使用实例分析
2011/04/08 PHP
PHP 命令行工具 shell_exec, exec, passthru, system详细使用介绍
2011/09/11 PHP
Codeigniter实现智能裁剪图片的方法
2014/06/12 PHP
PHP自定义函数实现格式化秒的方法
2016/09/14 PHP
PHP网页缓存技术优点及代码实例
2020/07/29 PHP
jQuery Form 页面表单提交的小例子
2013/11/15 Javascript
js导航栏单击事件背景变换示例代码
2014/01/13 Javascript
jquery实现页面图片等比例放大缩小功能
2014/02/12 Javascript
jQuery入门基础知识学习指南
2015/08/14 Javascript
vue实现添加标签demo示例代码
2017/01/21 Javascript
微信小程序 页面跳转及数据传递详解
2017/03/14 Javascript
node.js调用C++函数的方法示例
2018/09/21 Javascript
使用Node.js写一个代码生成器的方法步骤
2019/05/10 Javascript
微信小程序自定义tabbar custom-tab-bar 6s出不来解决方案(cover-view不兼容)
2019/11/01 Javascript
使用Vue-cli 中为单独页面设置背景图片铺满全屏
2020/07/17 Javascript
[05:46]2018完美盛典-《同梦共竞》
2018/12/17 DOTA
用xpath获取指定标签下的所有text的实例
2019/01/02 Python
在django admin中添加自定义视图的例子
2019/07/26 Python
python3.8 微信发送服务器监控报警消息代码实现
2019/11/05 Python
wxPython实现文本框基础组件
2019/11/18 Python
Tensorflow累加的实现案例
2020/02/05 Python
Python基于jieba, wordcloud库生成中文词云
2020/05/13 Python
Python socket服务常用操作代码实例
2020/06/22 Python
canvas学习和滤镜实现代码
2018/08/22 HTML / CSS
澳大利高级泳装品牌:Bondi Born
2018/05/23 全球购物
函授自我鉴定
2013/11/06 职场文书
回门宴新郎答谢词
2014/01/12 职场文书
关于赌博的检讨书
2014/01/24 职场文书
销售人员职业生涯规划范文
2014/03/01 职场文书
欢度春节标语
2014/07/01 职场文书
乡镇2014法制宣传日活动总结
2014/11/01 职场文书
刑事和解协议书范本
2014/11/19 职场文书
安全第一课观后感
2015/06/18 职场文书
创业计划书介绍
2019/04/24 职场文书
创业计划书之少年玩具店
2019/09/05 职场文书
python基础学习之递归函数知识总结
2021/05/26 Python