ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
目录 (づ ̄ 3 ̄)づ=> [TOC] ## 引入 ``` let fs = require('fs'); ``` ## 读操作 ### fs.readFileSync(路径[,编码]) ``` 1.路径必须正确否则报错 2.默认为utf8方法 3.此方法为同步方法 let result = fs.readFileSync('./1.txt','utf8'); ``` ### fs.readFile(路径[,编码],callback) ``` 回调是必须的,因为异步方法木有返回值,需通过回调取得值进行下一步操作 fs.readFile('index.js','utf8',function(err,data){ //err错误第一 if(err)return console.log(err); // fs.readFile。。。 }); ``` ## 写操作 ### fs.writeFileSync(path,data[,options],callback) ### fs.writeFile(path,data[,options],callback) ``` fs.writeFile('1.txt','{name:1,age:2}',function(err){ ... }); ``` ## 精度读/写操作 ``` let fs = require('fs'); /** * r 读取 * s 同步 * + 增加相反操作 * x 排他(我读的时候别人不能) * r+ w+区别:当文件不存在时,r+不会创建,而会导致调用失败,但w+会创建 * 如果文件存在,r+不会自动清空文件,但w+会自动把已有文件的内容清空 * rs忽略缓存 * wx 排他写入 * a 追加写入 */ /** * chmod */ // fs.writeFile('./2.txt','data',{encoding:'base64',flag:'a',mode:0o666},function(err){ // console.log(err); // }); // fs.appendFile('./2.txt','data',function(err){ // console.log(err); // }); // fs.readFile('./2.txt',{encoding:'utf8',flag:'r'},function(err,data){ // console.log(data); //由于上面时base64写入的,这里用utf8解出来是乱码 // }) //---------------------------------- //以上都是把文件当成一个整体来操作的 //当文件特别大的时候,大于内存的时候是无法执行这样的操作的 //我们需要精确的控制读取的字节 //file descriptor 文件描述符 //每当打开一个文件,操作系统就给这个文件分配一个数字,代表这个文件 //0 标准输入 1标准输出 2错误输出 // process.stdin.on('data',function(data){ //标准输入 // console.log(data); //监听控制台输入 打印出来 // }) // process.stdout.write('hello'); // process.stderr.write('wrong'); fs.write(2,Buffer.from('a'),0,1,null,function(){ //0标准输入 //1向标准输出里写 //2向错误输出里写 //fd向文件里写 //没打开一个文件 描述符会+1 }) process.stdin.on('data',function(data){ //标准输入 console.log(data); //监听控制台输入 打印出来 }) // fs.open('./2.txt','r',0o666,function(err,fd){ // // console.log(fd);//3 // //read可以精确的读一个文件 // //buff读到哪个buff里 //偏移量读到buff的哪个位置 //length从文件读取几个字节 //position 从文件哪里开始读取 //不填表示当前位置 内部有一个指针 // //bytesRead 实际读到的字节 // let buff = Buffer.alloc(6); // fs.read(fd,buff,0,3,null,function(err,bytesRead,buffer){ //buffer同buff // console.log(buff.toString()); //123 // fs.read(fd,buff,3,3,null,function(err,bytesRead,buffer){ //buffer同buff // console.log(buff.toString()); //123456 // }) // }) // }) fs.open('./2.txt','w',0o666,function(err,fd){ fs.write(fd,Buffer.from('a'),0,1,null,function(err,bytesWritten){ console.log(bytesWritten); fs.fsync(fd,function(err){ fs.close(function(){ console.log('关闭') }) }) }) }) ``` ### 精度写入时r+与a mod的区别 ``` let fs = require('fs'); fs.open('./2.txt','r+',0o666,function(err,fd){ console.log(fd); //offset length position fs.write(fd,Buffer.from('嘿哈'),3,3,6,function(){ //如果mode为a,那么position是无效的 //要使position有效必须为r+ //position有3个的偏移 3代表可见位为0的索引的位置 }) }) ``` ### 读一点写一点 ``` let fs = require('fs'); //实现节约内存的拷贝,读一点写一点 const BUFFER_SIZE = 3; //缓存大小为3个字节 function copy(src,target){ fs.open(src,'r',0o666,function(err,readFd){ fs.open(target,'w',0o666,function(err,writeFd){ let buff = Buffer.alloc(BUFFER_SIZE); !function next(){ fs.read(readFd,buff,0,BUFFER_SIZE,null,function(err,bytesRead,buffer){ if(bytesRead<=0) return; fs.write(writeFd,buff,0,bytesRead,null,next); }); }(); }) }) } copy('1.txt','2.txt'); //1拷贝到2 ``` ## 一个简单的copy文件方法实现 ``` let fs = require('fs'); //同步copy方法 function copy(origin,target){ let result = fs.readFileSync(origin,'utf8'); fs.writeFileSync(target,result); } //异步copy方法 function copySync(origin,target){ fs.readFile(origin,'utf8',function(err,data){ if(err) console.log(err); fs.writeFile(target,data,function(err){ if(err) console.log(err); }) }) } ``` ## 文件状态 ``` fs.stat('1.txt',function(err,stats){ //若文件存在,stats为一个对象,err为null //若不存在,stats为undefined,err为一个对象 console.log(stats); console.log(stats.isFile()); //true console.log(stats.isDirectory()); //false }) >>> Stats { dev: 1002684, mode: 33206, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: undefined, ino: 562949953725509, size: 26, blocks: undefined, atimeMs: 1515755716214.5186, mtimeMs: 1515755716216.5188, ctimeMs: 1515755716334.5254, birthtimeMs: 1515755319871.849, atime: 2018-01-12T11:15:16.215Z, mtime: 2018-01-12T11:15:16.217Z, ctime: 2018-01-12T11:15:16.335Z, //ctime触发的范围比mtime更广 birthtime: 2018-01-12T11:08:39.872Z } ``` ## 递归创建/删除文件夹及文件 利用stat判断文件是否存在 ``` let fs = require('fs'); function mkdirp (url){ //??分隔符是哪个 let urlArr = url.split('/'), index = 0; mkdir(urlArr[index]); function mkdir(path){ if(index>urlArr.length)return; fs.stat(path,function(err,stats){ if(err){ //说明文件不存在需要创建 fs.mkdir(path,function(err){ if(err) return console.log(err); mkdir(urlArr.slice(0,++index).join('/')); }) }else{ //说明已经存在跳过创建继续查看下一级 mkdir(urlArr.slice(0,++index).join('/')); } }); } } fs.mkdir('mkdir1',function(err){ console.log(err); }); mkdirp('a/b/c/d'); ``` 利用access判断文件是否存在 ``` //如何创建目录 let fs = require('fs'); //当创建目录的时候必须要求父目录是存在的 // fs.mkdir('a/b',function(err){ // console.log(err); // }) //判断一个文件或目录 是否存在 fs.exists(已废弃) // fs.access('a',fs.constants.R_OK,function(err){ // console.log(err); // }) /** * 递归异步创建目录 * @param dir */ function mkdirp(dir){ let paths = dir.split('/'); // [a,b,c] !function next(index){ if(index > paths.length) return; let current = paths.slice(0,index).join('/'); //第一次0,1 为a fs.access(current,fs.constants.R_OK,function(err){ if(err){ fs.mkdir(current,0o666,()=>next(index+1)); }else{ next(index+1); } }) }(1); } mkdirp('a/b/c'); // //获取一个目录下面的所有文件或目录 // fs.readdir(); // //删除一个文件 // fs.unlink(path); // //删除一个空目录(目录里有东西删不了) // fs.rmdir('a'); /** * 同步递归删除 * @param dir */ function rmdirpSync(dir){ let files = fs.readdirSync(dir); files.forEach(function(file){ let current = dir+'/'+file ,child = fs.statSync(current); if(child.isDirectory()){ rmdirp(current); }else{ fs.unlinkSync(current); } }); //删除本目录下的文件后删除自己 fs.rmdirSync(dir); } rmdirpSync('a') ``` 异步递归删除 ``` function rmDirAsync(dir,callback) { fs.readdir(dir, 'utf8', function (err, files) { !function next(index) { if (err) return console.error(err); if (files.length == 0 || index >= files.length) { fs.rmdir(dir, function (err) { if (err) console.error(err); callback && callback(); }); } else { let childPath = path.join(dir,files[index]) fs.stat(childPath, function (err, stats) { if (err) { console.error(err); return reject(err); } if (stats.isDirectory()) { rmDirAsync(childPath,()=>next(index+1)) } else{ fs.unlink(childPath, function (err) { if (err) { console.error(err); } next(index + 1); }); } }) } }(0); }); } ``` ## API记忆 - readFile/writeFile 区别在于 writeFile 的 `options` 参数中多了一个 `mode` - readFile没有指定编码时读取出来的是buffer,注意:如果一个文件描述符被指定为 path,则它不会被自动关闭。 - writeFile 如果 data 是一个 buffer,则忽略 encoding 选项。它默认为 'utf8',data 可以是一个字符串或一个 buffer。 - xxFile 和 read/write 的区别在于,不能单独使用read/write 必须配合 `fs.open` 打开文件先,且 `options` 参数中的 `flag` [,mode] 给了 `open`,自己只保留 `encoding`。 - write(string)和 write(buffer)的区别在于write(string)可配置 `encoding` - read 和 write 的区别在 read没有encoding,因为read的单位只能是buffer,而write时还可以是字符串。 ## 三种档次类读写操作的比较 ![](https://box.kancloud.cn/95893dcc490e5b897fdc921f3c81eb82_1831x1039.png)