人缺的不是天赋而是志向,不是成功的能力而是努力的意志。——卜尔维文章同步到github博客:https://github.com/koala-codi...前言文件操作是开发过程中不可或缺的一部分。Node.js中的fs模块是对文件操作的封装,提供了文件读取、写入、重命名、删除、遍历目录、链接等POSIX文件系统操作。与其他模块不同的是,fs模块中的所有操作都提供了异步和同步两种版本。有sync后缀的方法是同步方法,没有sync后缀的方法是异步方法。计算机系统和文件概述文章一些常识--权限位模式--标志位--文件描述符fsNode.js中fs模块的API详解及对应Demo--常规文件操作--高级文件操作--Node.js中文件目录操作fs模块的api对应demofs模块的应用场景和实战训练(复制大小文件)。面试会问fs模块有几个常用函数?什么情况下使用fs.open读取文件?用fs模块写个复制大文件的例子(注意大文件)?文件常识计算机中的一些文件知识,文件权限位模式,标识位标志,文件描述符fd等,你需要了解。这些内容对你学习fs的api、记忆和使用都有很大的帮助。权限位模式因为fs模块需要操作文件,所以会涉及到操作权限的问题,所以需要知道文件权限是什么,有什么权限。文件权限表:在上表中,我们可以看到系统分配了三类权限,分别是文件所有者(自己)、文件所属组(家人)和其他用户(陌生人),以及文件操作权限分为三种,read,write,execute。数字以八进制数表示。有权限的八进制数是4、2、1,没有权限的是0。为了便于理解,我们可以在任意目录下打开Git,使用Linux命令ls-al查看drwxr-xr-x目录下文件和文件夹的权限1koala1971210Jun2814:41core-rw-r--r--1koala197121293Jun2317:44index.md在上面的目录信息中,很容易看到用户名、创建时间和文件名等信息,但最重要的是第一项在开始(十个字符)。第一位代表是文件还是文件夹,d开头代表文件夹,-开头代表文件,后面九位代表当前用户的权限位,用户所属组属于,和其他用户。除以三个数字,分别代表读(r)、写(w)和执行(x),-表示当前位没有对应的权限。权限参数方式主要针对Linux和Unix操作系统。Window默认的权限是可读、可写、不可执行,所以权限位数表示为0o666,转换后的十进制表示为438。在flagNode.js中,flag表示文件的操作方式,如可读、可写、可读可写等。下面用一张表来表示标志位及其对应的文件操作含义。符号含义r读取文件,如果文件不存在则抛出异常。r+读写一个文件,如果文件不存在则抛出异常。rs读写文件,指示操作系统绕过本地文件系统缓存。w写入文件,如果文件不存在则创建,如果存在则清空写入。wx写入文件并以独占方式打开它。w+读写文件,文件不存在则创建,存在则清空后再写入。wx+和w+类似,都是独占打开的。a追加写入,如果文件不存在,则创建文件。ax类似于a,独占打开。a+读取并追加写入,如果不存在则创建。ax+和a+类似,都是独占打开的。上表是这些flags的具体字符和含义,但是flags不经常用,也不好记,所以下面总结了一个加快记忆的方法。r:读w:写s:同步+:增加相反的操作x:独占方式r+和w+的区别,当文件不存在时,r+不会创建文件,但会抛出异常,而w+会创建文件;如果文件存在,r+不会自动清除文件,但w+会自动清除已有文件的内容。文件描述符fs操作系统为每个打开的文件分配一个称为文件描述符的数字标识符。文件操作使用这些文件描述符来识别和跟踪每个特定文件。Window系统使用不同但相似的概念。为了方便用户,NodeJS抽象了不同操作系统之间的差异,并为所有打开的文件分配了数字文件描述符。在Node.js中,每操作一次文件,文件描述符就会递增,文件描述符一般从3开始,因为前面有3个特殊的描述符,0、1、2,分别代表process.stdin(标准输入)、process.stdout(标准输出)和process.stderr(错误输出)。文件操作完整性读写文件操作fileread-fs.readFilefs.readFile(filename,[encoding],[callback(error,data)]filereadfunction接收第一个必传参数filename,表示读取的文件名。第二个参数encoding可选,表示文件的字符编码,第三个参数callback是一个回调函数,用于接收文件的内容,说明:如果不指定encoding,则callback为第二个参数,callback函数提供两个参数err与data,err表示是否有错误,data为文件内容,如果指定了encoding,data为解析后的字符串,否则为Buffer形式表示的二进制数据。演示:constfs=require('fs');constpath=require('path');constfilePath=path.join(__dirname,'koalaFile.txt')constfilePath1=path.join(__dirname,'koalaFile1.txt'')//--异步读文件fs.readFile(filePath,'utf8',function(err,data){console.log(data);//程序员成长指南});//--同步读Fetch文件constfileResult=fs.readFileSync(filePath,'utf8');console.log(fileResult);//程序员长大写文件到fs.writeFilefs.writeFile(filename,data,[options],callback)file第一个必选参数写操作的参数是filename,表示要读取的文件名。第二个参数是要写入的数据。第三个参数option是一个对象,如下编码{String|null}default='utf-8'mode{Number}default=438(aka0666inOctal)flag{String}default='w'这时候第一章提到的计算机知识就会用到。标志值,默认为w,会清空文件再写入。标志值,r代表读文件,w代表写文件,a代表追加。demo://写入文件内容(如果文件不存在,则创建一个文件)//写入时,先清空文件fs.writeFile(filePath,'写入成功:程序员成长指南',function(err){if(err){throwerr;}//写入成功后读取测试vardata=fs.readFileSync(filePath,'utf-8');console.log('newdata-->'+data);});//文件追加也可以通过写文件和使用flags来实现fs.writeFile(filePath,'程序员成长指南添加的数据',{'flag':'a'},function(err){if(err){throwerr;}console.log('success');vardata=fs.readFileSync(filePath,'utf-8')//写入成功后读取测试console.log('Addeddata-->'+数据);});FileAppend-appendFilefs.appendFile(filename,data,[options],callback)第一个必选参数filename表示要读取的文件名。第二个参数data,data可以是任意字符串或者cache第三个参数option是一个对象,与write不同的是[options]的flag默认值为“a”,所以它以追加的方式写入数据。说明:该方法异步写入数据Insert到文件中,如果文件不存在,会自动创建demo//--异步另一个文件追加操作(非覆盖模式)//写入文件内容(如果文件不存在,会创建一个文件)fs.appendFile(filePath,'新数据程序员成长指南北456',function(err){if(err){throwerr;}//写入成功后读取测试var数据=fs.readFileSync(文件路径,'utf-8');console.log(data);});//--同步另一个文件追加操作(非覆盖模式)fs.appendFileSync(filePath,'同步追加新数据)');copyfile-copyFilefs.copyFile(filenameA,filenameB,callback)第一个参数为原文件名,第二个参数为要复制到demo中的文件名://复制filePath文件内容到filePath1文件内容fs.copyFileSync(filePath,filePath1);letdata=fs.readFileSync(filePath1,'utf8');console.log(数据);//程序员删除文件的成长指南-unlinkfs.unlink(filename,callback)第一个参数文件路径大家应该都知道,我就不赘述了第二个回调函数callbackdemo://--异步文件删除fs.unlink(filePath,function(err){if(err)return;});//--同步删除文件fs.unlinkSync(filePath,function(err){if(err)return;});指定位置读写文件操作(高级文件操作)接下来的高级文件操作会和上面的有些不同,过程稍微复杂一些,需要先用fs.open打开文件,然后就可以了使用fs.read读取,或使用fs.write写入文件,最后,您需要使用fs.close关闭文件。特别说明:read方法与readFile不同,一般针对文件过大无法一次将所有内容读入缓存或者文件大小未知的情况,多次读入Buffer。如果想了解Buffer,可以阅读NodeJS——Buffer解读。(注意这个被我的文章换掉了)打开文件-fs.openfs.open(path,flags,[mode],callback)第一个参数:文件路径第二个参数:同上面提到的标识符flagbeginning第三个第一个参数:[mode]为文件的权限(可选参数,默认值为0666)第四个参数:callback回调函数demo:fs.open(filePath,'r','0666',function(err,fd){console.log('hahaha',fd);//返回的第二个参数是一个整数,表示打开文件返回的文件描述符,也就是窗口中的文件句柄})demo说明:第二个返回的参数是一个整数,表示打开文件返回的文件描述符。在window中也称为文件句柄,文件描述符在开头也有说明。文件读取-fs.readfs.read(fd,buffer,offset,length,position,callback);六个参数fd:文件描述符,需要先用open打开,fs.open打开成功后返回的文件描述符;buffer:Buffer对象,v8引擎分配的一段内存,要读取的Buffer内容进入;offset:整数,写入Buffer缓冲区的初始位置,以字节为单位;length:整数,读取文件长度;position:整数,读取文件的初始位置;文件大小以字节为单位Bufferobject),读取执行完成后执行。demo:constfs=require('fs');letbuf=Buffer.alloc(6);//创建一个长度为6字节的buf缓存对象//打开文件fs.open('6.txt','r',(err,fd)=>{//读取文件fs.read(fd,buf,0,3,0,(err,bytesRead,buffer)=>{console.log(bytesRead);console.log(buffer);//继续读取fs.read(fd,buf,3,3,3,(err,bytesRead,buffer)=>{console.log(bytesRead);console.log(buffer);console.log(buffer.toString());});});});//3//
