详解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 npm package.json中文文档
Sep 04 NodeJs
基于NodeJS的前后端分离的思考与实践(六)Nginx + Node.js + Java 的软件栈部署实践
Sep 26 NodeJs
nodejs通过phantomjs实现下载网页
May 04 NodeJs
深入nodejs中流(stream)的理解
Mar 27 NodeJs
详解nodejs操作mongodb数据库封装DB类
Apr 10 NodeJs
nodejs创建简易web服务器与文件读写的实例
Sep 07 NodeJs
nodejs实现截取上传视频中一帧作为预览图片
Dec 10 NodeJs
关于Mac下安装nodejs、npm和cnpm的教程
Apr 11 NodeJs
关于NodeJS中的循环引用详解
Jul 23 NodeJs
Nodejs 识别图片类型的方法
Aug 15 NodeJs
在NodeJs中使用node-schedule增加定时器任务的方法
Jun 08 NodeJs
在nodejs中创建child process的方法
Jan 26 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判断当前操作系统类型
2015/10/28 PHP
浅谈php中urlencode与rawurlencode的区别
2016/09/05 PHP
PHP回调函数简单用法示例
2019/05/08 PHP
Laravel使用原生sql语句并调用的方法
2019/10/09 PHP
Jquery 点击按钮显示和隐藏层的代码
2011/07/25 Javascript
javascript 进阶篇3 Ajax 、JSON、 Prototype介绍
2012/03/14 Javascript
jQuery fadeTo方法调整图片的透明度使用介绍
2013/05/06 Javascript
仿百度联盟对联广告实现代码
2014/08/30 Javascript
jquery ajax 如何向jsp提交表单数据
2015/08/23 Javascript
JS图片定时翻滚效果实现方法
2016/06/21 Javascript
JS实现简易刻度时钟示例代码
2017/03/11 Javascript
微信小程序表单验证form提交错误提示效果
2020/06/19 Javascript
Vue.set() this.$set()引发的视图更新思考及注意事项
2018/08/30 Javascript
浅析JS中什么是自定义react数据验证组件
2018/10/19 Javascript
vue 项目 iOS WKWebView 加载
2019/04/17 Javascript
nodejs实现的http、https 请求封装操作示例
2020/02/06 NodeJs
vue-cli设置css不生效的解决方法
2020/02/07 Javascript
[08:47]2018国际邀请赛 OG战队举杯时刻
2018/08/29 DOTA
python连接oracle数据库实例
2014/10/17 Python
Python中使用dom模块生成XML文件示例
2015/04/05 Python
Python元字符的用法实例解析
2018/01/17 Python
python3.6利用pyinstall打包py为exe的操作实例
2018/10/31 Python
python tkinter控件布局项目实例
2019/11/04 Python
Python 下载及安装详细步骤
2019/11/04 Python
使用 Supervisor 监控 Python3 进程方式
2019/12/05 Python
传统HTML页面实现模块化加载的方法
2018/10/15 HTML / CSS
网购亚洲时装、美容产品和生活百货:YesStyle
2016/09/15 全球购物
Shoes For Crews法国官网:美国领先的防滑鞋设计和制造商
2018/01/01 全球购物
英国女性运动服品牌:Sweaty Betty
2018/11/08 全球购物
公务员年总结的自我评价
2013/10/25 职场文书
信用社员工先进事迹材料
2014/02/04 职场文书
机关道德讲堂实施方案
2014/03/15 职场文书
韩语专业职业生涯规划范文:成功之路就在我们脚下
2014/09/11 职场文书
2015年机关纠风工作总结
2015/05/15 职场文书
Pygame如何使用精灵和碰撞检测
2021/11/17 Python
Java 多态分析
2022/04/26 Java/Android