文件系统(FileSystem)
文件系统模块
对于文件无外乎创建修改添加。
File System - 文件系统模块 - require('fs')
fs模块是核心模块,需要使用require导入后使用。该模块提供了操作文件的一些API
fs.open(path, flags, [mode], callback)
–异步版的打开一个文件。一共接受4个参数,3个可选
path:要打开文件的路径
flags:打开方式——常用的有读()/写。会影响后续的打开方式
[MODE]:设置文件的模式:读、写、执行4/2/1
callback:回调文件打开后的执行后续又包括两个参数(1)err:文件打开失败的错误保存在err,成功则为null。(2)fd:被打开文件的标示和定时器,后续可以根据编号查找打开的是哪个文件。
在1.js同目录下创建一个内容为abcd的1.txt文件,对1.js输入
var fs=require('fs');//引入fs模块
fs.open('1.txt','r',function (err,fd) {//读
console.log(err);//返回null,证明打开成功
console.log(fd);//返回3
});
如果你打开
fs.openSync(path, flags, [mode])
–fs.open() 的同步版,读取方式是以同步的方式执行。不是以回调的方式处理。现在来看看他俩的区别。
I/O读取是需要时间的。异步加载的顺序:
var fs=require('fs');//引入fs模块
fs.open('1.txt','r',function (err,fd) {
console.log(fd);//第二个输出
});
console.log('ok');//第一个输出
而同步不需要回调。直接返回fd值。代码就好看多了。
var fd=fs.openSync('1.txt','r');//同步不需要回调,直接有返回值
console.log(fd);
console.log('ok2');
fs.read(fd, buffer, offset, length, position, callback)
–从指定的文档标识符fd读取文件数据。fd就是open回调函数中的标示编号,buffer对象,offset:新的内容添加到buffer的其实位置,length添加到buffer的长度,position:读取位置,callback回调函数
var fs=require('fs');//引入fs模块
fs.open('1.txt','r',function (err,fd) {
if(err){
console.log('失败')
}else{
var bf1=new Buffer(10);
console.log(bf1);//定义用来存放内容的buffer
fs.read(fd,bf1,0,4,null,function (err,len,newBf) {
//console.log(err)//返回为null
//console.log(len)//返回4
//console.log(newBf)//就是被修改后的bf1
console.log(bf1);
});//把读取的内容(4位),从第0位起放到bf1中
}
});
输出结果:
buffer对象的前4位就是abcd。
fs.readSync(fd, buffer, offset, length, position)
–fs.read 函数的同步版本。 返回bytesRead的个数。
fs.write(fd, buffer, offset, length[, position], callback)
–通过文件标识fd,向指定的文件中写入buffer。fd标识,buffer:要写入的数据,offset:在buffer中要写入数据的起始位置,length要写入buffer数据的长度,position:fd中的起始位置,callback回调。当对文件进行写操作时,open方式应该是r+
而不是r
。
var fs=require('fs');//引入fs模块
fs.open('1.txt','r+',function (err,fd) {
if(err){
console.log('打开失败')
}else{
var bf1=new Buffer('123');
fs.write(fd,bf1,0,3,0,function () {
console.log(arguments);
});//针对fd文件写入bf1的内容。读取1.txt第0到第3个的内容,并从第0个开始修改为123
}
});
输出{ '0': null, '1': 3, '2': <Buffer 31 32 33> }
再看1.txt:内容变成了123d
。
fs.write(fd, data[, position[, encoding]], callback)
–把data写入到文档中通过指定的fd,如果data不是buffer对象的实例则会把值强制转化成一个字符串。
以上那么长一段可以有简化写法:
fs.write(fd,'1234',5,'utf-8');
——从第4位开始添加abcd——>1234abcd
fs.writeSync(fd, buffer, offset, length[, position])
–fs.write() 的同步版本
fs.writeSync(fd, data[, position[, encoding]])
–fs.write() 的同步版
fs.close(fd, callback)
–关闭一个打开的文件
fs.closeSync(fd)
–fs.close() 的同步版本
fs.writeFlie(filename, data, [options], callback)
–异步的将数据写入一个文件,如果文件不存在则新建, 如果文件原先存在,会被替换。 data 可以是一个string,也可以是一个原生buffer。
想一个指定的文件写入数据。如果存在会覆盖掉原来的。
var fs=require('fs');//引入fs模块
var filename='2.txt';
fs.writeFile(filename,'hello',function () {
console.log(arguments);
});
中午段代码创建你了一个2.txt,把hello写进去了。
fs.writeFileSync(filename, data, [options])
–fs.writeFile的同步版本。注意:没有callback,也不需要
fs.appendFile(filename, data, [options], callback)
–异步的将数据添加到一个文件的尾部,如果文件不存在,会创建一个新的文件。 data 可以是一个string,也可以是原生buffer。
var fs=require('fs');//引入fs模块
var filename='2.txt';
fs.appendFile(filename,'-djtao',function () {
console.log(arguments)
});
fs.appendFileSync(filename, data, [options])
–fs.appendFile的同步版本。
fs.readFile(filename, [options], callback)
–异步读取一个文件的全部内容
var fs=require('fs');//引入fs模块
fs.readFile('2.txt',function () {
console.log(arguments)
});
打印结果是:
{ '0': null, '1': <Buffer 64 6a 74 61 6f 2d 64 6a 74 61 6f> }
第一个参数是错误,第二个参数个buffer对象。描述是2.txt的内容(djtao-djtao)。
所以完整写法应该是:
var fs=require('fs');//引入fs模块
fs.readFile('2.txt',function (err,value) {
//console.log(arguments)
if(err){
console.log('读取失败')
}else{
console.log(value.toString())//2.txt的文本内容
}
});
fs.readFileSync(filename, [options])
–fs.readFile的同步版本
fs.exists(path, callback)
–检查指定路径的文件或者目录是否存在
直接来看一个结合写入和追加判断的方法
var fs=require('fs');//引入fs模块
var filename='3.txt';
fs.exists(filename,function (isExists) {
console.log(isExists);//
if(!isExists){//如果不存在,写入djtao
fs.writeFile(filename,'djtao',function (err) {
if(err){
console.log('出错了,创建失败');
}else{
console.log('创建新的文件成功并写入内容')
}
})
}else{//如果存在,追加-djtao
fs.appendFile(filename,'-djtao',function (err) {
if(err){
console.log('新的内容追加失败');
}else{
console.log('新的内容追加成功!');
}
})
}
})
使用appendFile实际上是不必要的。这里为了演示机制。
第一次运行结果,因为3.txt原本是不存在的,所以创建3.txt并写入文件‘djtao’:
我们在运行一次,此时因为存在了3.txt,所以3.txt内容变成了:djtao-djtao结果是:
fs.existsSync(path)
–fs.exists的同步版本
var fs=require('fs');//引入fs模块
var filename='4.txt';
//以下采用同步的写法:
if(!fs.existsSync(filename)){//如果文件不存在
fs.writeFileSync(filename,'djtao');
console.log('新文件创建成功!');
}else{//如果文件存在,追加
fs.appendFileSync(filename,'-djtao')
console.log('新内容追加成功!')
}
从结果来看效果和上例是一样的。
fs.unlink(path, callback)
–删除一个文件
var fs=require('fs');//引入fs模块
fs.unlink('3.txt',function (err) {
if(err){
console.log('删除失败')
}else{
console.log('删除成功')
}
});
回调函数只有一个参数err,如果不存在要删除的文件,err就不为null。
fs.unlinkSync(path)
–fs.unlink() 的同步版本
fs.rename(oldPath, newPath, callback)
–重命名
var fs=require('fs');//引入fs模块
fs.rename('2.txt','2.newTxt',function (err) {
if(err){
console.log('重命名失败')
}else{
console.log('成功!')
}
})
fs.renameSync(oldPath, newPath)
–fs.rename() 的同步版本
–
fs.stat(path, callback)
–读取文件信息
var fs=require('fs');//引入fs模块
fs.stat('1.txt',function (err,info) {
//console.log(arguments)
})
info是个json信息,包括def创建时间,修改时间,字节长度,是属于文件(mode:33206)还是文件夹(mode:16822)等等。不同操作系统返回的内容有所不同。
fs.statSync(path, callback)
–fs.stat() 的同步版本
–
fs.watch(filename, [options], [listener])
–观察指定路径的改变,filename 路径可以是文件或者目录
它是一个事件。(不稳定,可能有bug。慎重使用)
第三个监听器是个回调函数,路径被改变时会被触发。
fs.mkdir(path, [mode], callback)
–创建文件夹,path指的是路径,mode是指读写模式,最后一个是回调。
fs.rmdir(path, callback)
–删除文件夹
为了演示,以下结合fs.rmdir进行操作:在当前目录下创建一个名字为1的文件夹,如果1文件夹已经存在,就删掉。
var fs=require('fs');//引入fs模块
fs.mkdir('./1',function (err) {
if(err){
console.log('创建失败,将删除名字为1的文件夹');
fs.rmdir('./1',function (eRr) {
if(!eRr){
console.log('删除成功')
}else{
console.log('删除失败!')
}
})
}else{
console.log('成功创建了一个名为1的文件夹')
}
});//在当前目录创建一个1文件夹。如果该文件夹存在则删除掉。
通过此方法也可以判断一个文件夹是否存在。
fs.mkdirSync(path, [mode])
–fs.mkdir的同步版本
fs.rmdirSync(path)
–fs.rmdir的同步版本
fs.readdir(path, callback)
–读取文件夹
接下来读取当前文件夹
var fs=require('fs');//引入fs模块
fs.readdir('./',function (err,fileList) {
console.log(err);
console.log(fileList);
});
输出
null
[ '1', '1.js', '1.txt', '2.js', '2.new.txt', '3.js' ]
表示当前文件夹下存在以下文件(夹)。存在一个数组里面。
接下来要进一步优化,做一个文件管理系统。之前有个stat方法可以判断文件信息.
var fs=require('fs');//引入fs模块
fs.readdir('./',function (err,fileList) {
fileList.forEach(function (f) {//循环数组每个元素,参数f每次循环的元素
//判断当前是文件还是文件夹
fs.stat(f,function (err,info) {
if(info.mode==16822){
console.log('[文件夹]'+f);
}else if(info.mode==33206){
console.log('[文件]'+f);
}else{
console.log('[其它]'+f);
}
});
})
});
输出结果
[文件夹]1
[文件]1.js
[文件]1.txt
[文件]2.js
[文件]2.new.txt
[文件]3.js
fs.readdirSync(path)
–fs.readdir同步版本