一、Buffer缓存区
在电脑中,所有的数据都是以二进制的形式存储的,而JavaScript语言本身是没有二进制数据类型的,而Node作为服务端需要处理像TCP网络流和文件流时的数据,就必须得使用二进制,因此在Nodejs中,定义了一个buffer类,用来创建一个专门存放二进制数据的缓存区
1.1 创建buffer
var buf1=new Buffer(10)——这里的10代表字节数
var buf2=new Buffer([1,2,3])——这里表示创建一个存数组的buffer数据
var buf3=new Buffer('string....','utf-8')——这里表示存放一个字符串
1.2 写入buffer内容
将一个buffer类型的数据写入到另一个buffer类型的数据中,进行整合;
语法:
buf.write(string,offset,length,encoding)
参数:
string:代表写入的内容
offset:代表开始写入的索引值
length:代表写入的字节数
encoding:代表编码格式,一般默认为utf-8;
【例】:
var buf1=new Buffer('aabbcc')
var buf2=new Buffer('ddee')
//将buf2的内容写入到buf1中
buf1.write(buf2.toString(),2,4,'utf8')
console.log(buf1.toString())
1.3 读取buffer
通过tostring()方法将buffer类型数据转换为字符串
buf.toString(encodeing,[start,[end)
enconding:编码格式
start:起始位置 end:结束位置
1.4 拷贝buffer
buf.copy(targetBuffer,targetstart,sourcestart,sourceend)
将一个buffer数据复制到另一个buffer中
参数:
targetBuffer:目标buffer,拷贝到的对象
targetstart:拷贝的起始位置
sourcestart:拷贝的内容从哪儿开始
sourcestart:拷贝的内容到哪儿结束
【例】:
var buf1=new Buffer('aabbcc')
var buf2=new Buffer('ddeeff')
buf1.copy(buf2,0,2,6)
console.log(buf2.toString()) //输出结果为bbccff
二、fs文件模块
fs文件模块也是nodejs中的核心模块之一,在nodejs的文件系统模块中,文件操作方法一般都有同步(带Sync)和异步两个版本
要使用文件模块,首先要引入fs,再使用其上的方法;
2.2 文件读取
1、同步读取 fs.readFileSync(path,options)
同步操作即只有当前代码执行完成了才会执行下一步操作,同步读取文件亦然
2、异步读取
fs.readFile(path,options,callback)
参数:
1)、path:为要读取的文件的路径,
2)、options:其他选项,如utf-8编码;
3)、callback:回调函数,有两个参数,err:默认为null,当文件读取失败时它会存储一些错误信息并返回,所以可以通过err来判断文件是否读取成功; data:当文件读取成功时,文件中的数据就存储在data中。
例:
var fs=require('fs') //引入文件模块
fs.readFile('./dong.html','utf-8',function(err,data){ //异步读取
if(!err){
console.log(data) //当文件读取成功时,输出读取的内容
}
})
注意:
1、在nodejs中,js格式,json模式文件可以不用写后缀,node在查找文件时会自动给它添加后缀,但其他文件需要加添加后缀,如这里的dong.html
2、若是当前目录下的文件,一定要在前面加上’./‘
2.3 文件信息
fs.stat(path,callback);
参数:
1)、path为文件的路径
2)、callback:回调函数 ,有两个参数,err:在获取文件信息失败时,会存储错误信息,stats:存储文件信息的参数。
stats:是fs.stats()对象,执行fs.stat后将stats类实例返回给其回调函数 ,因此可以通过stats对象上的isFile()方法来判断读取的是否为文件(而不是文件夹)
var fs=require('fs')
fs.stat('./router',function(err,stats){ //读取router文件夹
console.log(stats.isFile()) //判断文件夹是否为文件; 返回false
})
2.4 写文件
1、同步写入
fs.writeFileSync(filename,data,[options])
2、异步写入
fs.writeFile(filename,data,[options],callback);
参数:
1、filename:待写入的文件名,若没有则会自动创建相应的文件
2、data:写入的数据
3、options:其他选项,如utf-8
4、callback:回调函数,只有一个参数err,当写入失败时err包含了错误信息
var fs=require('fs')
fs.writeFile('./text.txt','写入到一个新的文件中','utf-8',function(err){
if(err)
console.log('写入失败')
})
以上代码将‘写入到一个新的文件中’这句话写入到text.txt文件中,node在查找文件时没有发现text.txt文件所以就会自动创建一个text.txt来写入。
2.5 fs删除文件
也有同步,异步两种方式,这里只以异步为例
fs.unlink(path,callback)
参数:path——文件路径;callback:回调函数,有一个参数err,当删除失败时会存放错误信息
例:
var fs=require('fs')
fs.unlink('./text',function(err){
if(err)
console.log(err)
})
2.6 fs读取文件夹目录
fs.readdir(path,callback)
readdir()方法可以读取文件夹的目录,即文件夹下有多少文件等
参数:
1、path:文件夹路径
2、callback:回调函数,有两个参数:err——读取失败时的错误信息,files——读取成功时的文件的集合,是一个数组,
例:
var fs=require('fs')
fs.readdir('./Router',function(err,files){
console.log(files) //输出:[ 'admin.js', 'user.js' ]
})
2.7 fs删除空文件夹
fs.rmdir(path,callback)
参数:
callback:回调函数有一个err参数用于存放错误信息
注意:只有空文件夹才能被删除,若文件夹不为空,则会报错 directory not empty
【实例】删除一个不为空的文件夹(它里面还有子文件夹)
如图:删除remove文件夹
分析:
要删除文件夹用rmdir()方法,但前提是文件夹为空,所以要先删除子文件,而子文件中又有文件夹所以要对子文件进行判断isFile(),若是文件就直接删除unlink,若是文件夹则进入到文件夹中删除子文件再删除文件夹。
var fs=require('fs');
var path='./remove'; //将路径用变量存储方便后面拼接子文件路径
//为了保证程序是按顺序执行的,所以下面都采用同步方法操作
//1、读取文件目录
function removeFile(path){
var files=fs.readdirSync(path);
for(var i=0;i<files.length;i++){
var pathf=path+'/'+files[i];//拼接子文件路径
var stats=fs.statSync(pathf)
if(stats.isFile()){
fs.unlinkSync(pathf); //若为文件则删除
}else{
removeFile(pathf)
}
};
fs.rmdirSync(path);
};
removeFile(path);
【注意】:
1、以上文件操作都是以同步方式进行的,因为同步能保证程序按顺序执行,若用异步操作则需要注意回调函数的执行顺序问题,因为很容易会出错。
2、要删除文件首先要判断其是否为文件,若是文件夹,则需要进入文件夹删除其子文件再删除文件夹
三、fs流
上面的文件操作方式都是一次性完整的读取文件,或写入文件,这对小文件的操作并没有问题,但当要操作的文件特别大时,由于内存限制缓存,所以会出现问题。因此,fs中还有一种fs流的方式来读取文件
流:在应用程序中,一组有序的,有起点和终点的字节数据的传输方式;
在应用程序中,各种对象之间数据的交换与传输都是先将该数据转换为各种形式的流数据(字节数据),再通过流的方式传输,到达目的对象时,将流数据 再转换为该对象中可用的数据。
fs流与fs直接读取的区别:fs直接读取是将数据一次性的完整读取出来放入缓存中,而fs流的方式则是将数据交换为流数据,再一点点的从一个对象传到另一个对象中去。
3.1 流读取
步骤:1、创建可读流; 2、处理流事件
var fs=require('fs'); //1、创建可读流
var stream=fs.createReadStream('./test') //()内为文件路径
stream.on('data',function(data){ //2、处理可读流事件(data读取文件事件)
console.log(data.toString());
});
stream.on('end',function(){ //3、处理可读流事件(end读取完成事件)
console.log('文件读取完成')
})
3.2 流写入
步骤:1、创建可写流; 2、处理流事件
var fs=require('fs');
var stream=fs.createWriteStream('./test') //1、创建可写流
stream.write('待写入的内容呢','utf-8'); //2、写入内容
stream.on('finish',function(){ //3、处理流事件
console.log('写入成功')
})
stream.on('error',function(){
console.log('写入失败')
})
四、流管道
管道pipe:提供了一个输出流到输入流的机制,通常用于从一个流中获取数据 并将数据传递到另一个流中。(比如:当一个对象的流入速度和流出速度不一样时,就可能会出现阻塞,这时就需要用管道机制pipe来解决。)
用法:
var fs=require('fs');
var streamRead=fs.createReadStream('./test2') //分别创建可读,可写流
var streamWrite=fs.createWriteStream('./test')
streamRead.pipe(streamWrite); //用管道将test2内容写入到test中
可见:用管道的方式可以省去很多代码啊有木有。
六、链式流
管道的读写方式是可以进行链式操作的,链式:即通过连接输出流到另一个流并创建多个流操作链机制。
var fs=require('fs');
var zlib=require('zlib') //引入压缩模块
fs.createReadStream('./test') //读取test文件并压缩创建为test.gz文件;
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('./test.gz'))
七、path路径模块
path路径模块也是nodejs自带的一个核心模块,用于操作路径
常用的有:
1、path.join(path1,path2,path3…)——连接路径,正确使用‘/’来创建路径
var fs=require('fs');
var path=require('path')
//删除test2文件,但不确定test2的路径时,用path.join写成绝对路径再删除
fs.unlinkSync(path.join(__dirname,'test2')) //dirname:根目录
2、path.resolve(from,to)——将to参数解析为绝对路径
3、path.parse(pathString)——返回路径字符串的对象(将路径字符串转为对象)
4、path.format(pathObject)——将路径对象转为字符串
5、path.isAblsolute(path)——判断是否为绝对路径
6、path.dirname(path)——返回路径中带文件夹的部分。