const fs = require('fs');
引入fs模块之后,可以利用其中的接口进行文件操作。
可以使用 fs.stat
函数查询,第一个参数为文件路径,第二个参数为查询完成之后的回调函数,回调函数接受一个参数,为查询的返回值。
返回值有文件的基本信息,具体就不列了,看文档即可。
该函数会将stats类的一个实例作为返回值传给回调,通过这个实例,我们可以调用以下函数:
在进行文件操作前,需使用 fs.open
函数打开文件,然后使用文件描述符调用回调。然后可以在回调函数中读写。
文件描述符按照我的理解,就是相当于把某一路径下的文件打开后,让一个变量指向他,这个变量是一个特殊对象,可以使用很多文件接口。
第一个参数为文件路径;第二个是一个标志位,表明文件以何种模式打开,例如有r、r+、w、w+等等,表示读取、读写等以及数据流的位置在何处;第三个参数就是回调函数了,回调第一个参数为错误捕获,第二个参数为文件描述符。
读取之前,请保证文件被打开,并且有一个缓冲区存放数据。(不知道缓冲区的可以参考此系列的第二篇博客)
fs.open('./x.text','r',function y(err,fd){
if(err) {throw err} // throw会自动return
let bf = new Buffer(1024);
let bfOffset = 0;
let bfLength = bf.length;
let filePosition = 100;
fs.read(fd,bfOffset,bfLength,filePosition,function read(err,readBytes){
if(err) {throw err};
// readBytes为读入缓存区的字节数,如果为0代表到达文件末尾
if(readBytes > 0) {
console.log(bf.slice(0,readBytes));
}
})
})
上述代码在打开文件之后,从缓冲区的第100个字节(filePosition)开始,读取随后的1024个字节的数据。仔细读一下代码,在对应看变量,大家应该很好理解每个参数是什么作用了。
注意:一旦将缓冲区传递给fs.open,缓冲区的控制权就移交给read命令,在没有返还控制权到你手上的时候,也就是回调函数没有被调用的时候,不应该对该缓冲区进行操作,不然会乱套,你在读或者写我也在读或者写,这就会造成想象得到和想象不到的很多问题。
使用 fs.write
,通过向其传递一个包含数据的缓冲区,可以实现写入。
fs.open('./x.text',"a",function w(err,fd){
let bf = new Buffer('writing this string'),
bfPosition = 0,
bfLength = bf.length,
filePosition = null;
fs.write(fd,bf,bfPosition,bfLength,filePosition,function(err,writen){
if(err) throw err;
console.log(writen);
})
})
上面的代码中,第一行用追加模式打开一个文件,然后在第六行向文件写入,传递的缓冲区包含以下信息:
filePosition的初值为null,表示从当前文件的游标处开始。
注意:和读取操作一样,不要随便操作缓冲区
上述所有例子中,都没有关闭文件,因为上面的代码只需要运行一次,运行完毕之后,程序退出,文件自动被关闭。但是实际代码中,一个文件被打开,那么就一定要被关闭。
如果想要关闭,那么就需要用到文件描述符(一个指向文件的对象)。
简单使用:
fs.close(fd,function(){
...
})
到目前为止,我们学习了用底层的基础语句来操作文件,而Node还有一种更高级的方式,就是使用 Stream
。这个会在后面讲到,很快就要讲到了。