fs对象的定义
fs是fileSystem的简称,表示文件系统,定义了处理文件和文件夹相关的方法。我们读取文件都是读取到的结果都是buffer二进制类型。
fs相关API
- fs.readFile异步获取文件
- fs.writeFile异步将buffer数据写入文件中
const fs = require('fs')
const path = require('path')
fs.readFile(path.resolve(__dirname,'3.fs.js'),function(err,data){
// readFile第一个参数是当前读取文件的路径,第二个参数是回调函数返回读取的信息以及错误信息
console.log(data.toString())
// writeFile写入文件第一个参数是写入的目录,第二个参数是写入的二进制内容,第三个参数是标识符,r表示这是一个读操作,w表示这是一个写操作,a表示这是一个追加操作
fs.writeFile(path.resolve(__dirname,'xxx.js'),data,{flag:'a'},function(err,data){
console.log('copy')
})
})
但是如果读取的文件是图片的话,转成字符串的话会是乱码。
- fs读取的内容都会放在内存当中。
- 如果文件过大的话就会浪费内存
- 淹没可用内存,大文件不能采用这种方式来操作,64k以上的文件做拷贝尽量不要使用readFile来实现。
文件系统提供的方法
- fs.open fs.write fs.close 手动读写文件
我们把内存当做参照物,要将一个文件的内容读取到内存中,实际上是做了写操作,从文件中读取出来内容然后再内存中进行写操作。
向文件中进行写操作,实际上是先从内存中读取内容,然后再写入文件中。 - 读操作的源码
const buffer = Buffer.alloc(3);
// fs.open的第一个参数是文件的路径,第二个参数是操作符,开启读写操作,第三个参数是回调函数 回调函数中返回的是错误信息还有一个是文件描述符 会生成一个表示对当前文件操作的符号
fs.open(path.reslove(__dirname,'./3.fs.js'),'r',function(err,fd){
// fs.read的参数第一个参数是fd文件描述符,第二个参数是读取内容要写入的对象,第三个参数是从buffer的哪个位置上面写,第四个参数是写入的长度,第五个参数是从文件的哪个位置开始读取,第六个参数是个回调函数包含着读取的实际字节数量
fs.read(fd,buffer,0,3,0,function(err,bytesRead){
console.log(bytesRead,buffer.toString())
// 读取完毕以后要将开启的权限关闭掉 调用close方法
fs.close(fd,()=>{
console.log('完成')
})
})
})
- 写操作的源码
// 在开启写操作的时候还可以传递mode参数表示写操作的权限,0o666是最大的权限,用8进制表示,chmod -R 7 7 7 代表的是最大权限 二爷一直4读书 r 4 1执行 2写 x 1 w 2
fs.open('./xxx.js','w',0o666,function(err,fd){
// fs.write方法第一个参数是写操作的描述符,第二个参数是读取的buffer对象,第三个参数是从buffer的哪里开始读取,第四个参数是读取到的位置,第五个参数是写入到文件的位置,第六个参数是回调函数,里面包含写入的个数和错误信息
fs.write(fd,buffer,0,3,0,function(err,written){
// written写入的实际个数
console.log(written)
})
})
读写操作我们已经清楚了,那么我们使用fs提供的方法实现一个copy文件的方法
- 由于我们要对文件做拷贝操作,所以我们开启读和写的权限,然后进行读操作以及写入操作
function copy(source,target,cb){
// 每次读取的流长度
const BUFFER_LENGTH = 3;
let read_position = 0; // 每次读取的位置
let write_position = 0; // 每次写入的位置
const buffer = Buffer.alloc(BUFFER_LENGTH); //声明字节长度为BUFFER_LENGTH的字节流
// 开启对源文件的读权限
fs.open(source,'r',function(err,rfd){
fs.open(target,'w',function(err,wfd){
function next(){
// read的参数 第一个参数是文件描述符 (开启对某个文件的读权限的),第二个参数是读出来的流存入的buffer对象,第三个参数是从buffer的哪个位置上面写,第四个参数是写入buffer的长度,第五个参数是从文件的哪个位置读
fs.read(rfd,buffer,0,BUFFER_LENGTH,read_position,function(err,bytesRead){
// 读取的字节数
if(err) return cb(err)
// 如果还有内容的话 就继续写入操作
if(bytesRead){
// 读出来在写进去第一个参数写入的文件的描述符 第二个参数是读取的buffer 第三个参数从buffer的哪里开始读取 第四个参数是读取几个字节 第五个参数是写入文件的位置
fs.write(wfd,buffer,0,bytesRead,write_position,function(err,written){
// 下次读取的位置
read_position += bytesRead;
write_position += bytesRead;
next();
})
}else{
// 关闭对文件的读写权限
fs.close(rfd,()=>{})
fs.close(wfd,()=>{})
cb('success copy')
}
})
}
next()
})
})
}
copy('./3.fs.js','./xxx.js',(text)=>{
console.log(text)
})
我们实现了拷贝文件的操作但是这种异步的方式会造成回调地狱以及不能设置读取文件的大小等等限制操作,所以为了解决问题我们需要使用stream对象来解决异步以及没有限制的问题。