Node.js(3)—— fs模块
对文件操作是在开发中十分重要且必不可少的一个环节。fs模块可以实现与硬盘的交互,例如文件的创建、移动、删除、重命名等,以及对文件内容的写入,读取和文件夹相关的操作。
目录
文件写入
写入文件内容
文件内容追加
文件流式写入
文件读取
常见文件读取应用场景
文件流式读取
运用
文件重命名和移动
文件删除
文件夹操作
1、创建文件夹
2、文件夹读取
3、删除文件夹
查看资源状态
path模块
文件写入
文件的写入在计算机中是十分常见的操作,比如:
- 下载文件
- 安装软件
- 保存程序日志(如git)
- 编辑器保存文件
- 视频录制
这些操作都用到了文件写入。
当需要持久化保存数据时,应该用到文件写入。
写入文件内容
在使用fs时,我们要先进行导入。
1.导入文件
const fs = require('fs');
require是一个全局的函数,用于导入模块,括号内必须写上 'fs' 才能正常导入。
2、写入文件
fs.writeFile();
使用writeFile来进行文件的写入,括号内填入参数。而参数一共有四个,分别为:文件名、待写入的数据、选项设置和写入回调。
比如我们想要对另外一个文件进行写入,这个地方暂时用不到选项设置,我们只用写其他三个参数:
const fs = require('fs');
fs.writeFile('./test.js','Hello World',err => {//如果写入失败,err == 错误对象//写入成功,err == nullif(err){console.log('写入失败');return;}else{console.log('写入成功');}
});
注意:若填入的文件名参数对应的文件不存在,则会自动创建一个对应的文件。
文件内容追加
内容的追加我们需要用到方法appendFile.如果test1文件中的内容如下:
现在我想要将test1中的文字内容追加为“Hello World!”,应该如何实现呢?
1、引入fs模块
2、调用appendFile方法,其同样具有那四个参数。
代码如下:
const fs = require('fs');
fs.appendFile('./test1.js','World!',err => {if(err){console.log('写入成功');return;}else{console.log('写入失败');}
})
文件流式写入
我们使用的方法为createWriteStream,它包含两个参数:path和option,表示文件路径和选项配置。
const fs = require('fs');
const ws = fs.createWriteStream('./test.txt');
ws.write('We will be building our backend on top of NodeJs,\n');//打开文件
ws.write('which is a JavaScript runtime based on Google`s Cheome V8 JavaScript engine.')
ws.close();//关闭
以上为该方法的使用。我们创建一个变量ws来选中对应的文件,使用createWriteStream后会打开文件,我们直接使用ws.write()就能向文件写入 内容了。最后书写完要使用ws.close进行关闭。
打开test.txt文件,可以看到写入成功。
和writeFile一次性写入不同,createWriteFile只要不主动关闭通道,就可以持续不断地写入内容。程序打开一个文件是需要消耗资源的,而流式写入方法可以减少打开文件的次数,减少资源的消耗。因此,流式写入适合 大文件写入和频繁写入 的场景 ;writeFile则适用于 导入频率较低 的场景。
关于流式写入,我们最后再来关注一下关闭通道。其实关闭通道有两种方式,按照之前的例子有:
ws.close();
ws.end();
两种方式都能实现通道的关闭。但其实我们不添加关闭命令,程序在执行完后也会自行关闭通道。所以去掉通道关闭命令代码我们发现效果和之前是一样的。
const fs = require('fs');
const ws = fs.createWriteStream('./test.txt');
ws.write('We will be building our backend on top of NodeJs,\n');//打开文件
ws.write('which is a JavaScript runtime based on Google`s Cheome V8 JavaScript engine.')
文件读取
下面我们来学习文件的读取。首先第一步,当然也要导入fs模块。之后我们使用readFile方法来进行读取,接受三个参数:path(文件路径)、option(文件配置)、callback(回调函数),返回值为undefined。
const fs = require('fs');
fs.readFile('./test.txt',(err,data) => {if(err){console.log('读取失败');return;}console.log(data.toString());
})
我们可以看见成功读取了文件内容并打印了出来。
常见文件读取应用场景
- 电脑开机
- 程序运行
- 编辑器打开文件
- 查看图片
- 播放视频
- 播放音乐
- Git查看日志
- 上传文件
- 查看聊天记录
文件流式读取
下面来看如何实现文件的流式读取。需要使用方法createReadStream。直接上代码:
const fs = require('fs');
const rs = fs.createReadStream('../test/test1.txt')//创建读取流对象
//绑定事件名为data的事件 chunk为回调函数
//当读取一次数据后就会执行一次回调
rs.on('data',chunk => {console.log(chunk);console.log(chunk.length);
})
这个地方的目录我们进行了修改:
test文件中的内容我们可以随意打几个英文字符。运行后就能看见对应文件中英文字符的十六进制码。下面我们再打印一下长度:
console.log(chunk.length);
之后再终端中运行就能查看到总字符长度了。
我们也可以在结尾加上可选事件作为结束。
rs.on('end',() => {console.log('读取完成');
})
运用
下面我们来做一个练习。如何对一个文件进行复制?
我们有以下方法来实现:
1、readFile,读取文件内容
const fs = require('fs')
let data = fs.readFile('../test/test1.txt');
//写入文件
fs.writeFileSync('../test/test1-re.txt',data);
这里Sync后缀表示同步,在执行一次性操作,代码量少,逻辑简单时使用同步效率更快。
2、流式
const fs = require('fs');
const rs = fs.createReadStream('../test/test2.txt');
const ws = fs.createWriteStream('../test/test2-re.txt');
rs.on('data',chunk=>{ws.write(chunk);
})
我们可以在最后查看总共消耗的资源,单位字节。
rs.on('end',() => {console.log(process.memoryUsage());
})
第一种方式也可以查看。我们可以相互对比两种方法消耗的资源,来比较哪种方法消耗资源更少。
这样我们就复制好了文件。
文件重命名和移动
重命名和移动需要用到同一个方法 rename 。在之前的例子上,我们的目录已经修改为:
移动也属于重命名。我们使用rename时可以将文件的路径重命名;rename也有参数,和之前的方法参数都是大同小异。参数有三个:当前路径、新路径和回调函数。
上代码:
const fs = require('fs');
//重命名
fs.rename('../test/test.txt','../test/test-rename.txt',err=>{if(err){console.log('操作失败');}console.log('操作成功');
})
//移动
fs.rename('../test/test1.txt','./test1.txt',err=>{if(err){console.log('操作失败');}console.log('操作成功');
})
之后目录发生了变化:
文件删除
文件删除使用unlink方法。直接上代码:
const fs = require('fs');
fs.unlink('../test/test-rename.txt',err=>{if(err){console.log('操作失败');return;}console.log('操作成功');
});
文件夹操作
我们在前面的例子上创建新文件夹都是使用键鼠操作,下面我们来学习如何在nodejs中进行相关的文件夹操作。
1、创建文件夹
创建文件夹使用方法mkdir。mkdir接收三个参数:path(文件夹路径)、options(选项配置)和callback(回调函数)。来看使用过程:
const fs = require('fs');
fs.mkdir('./draft',err => {if(err){console/log('创建失败');return;}console.log('创建成功');
});
我们给上文件夹的路径就能创建了。不过要注意不能写成下面的递归创建:
fs.mkdir('./fir/sec/thi',err => {if(err){console.log('创建失败');return;}console.log('创建成功');
})
这样会创建失败。文件夹不能这样直接递归创建。不过我们可以添加第二个选项配置参数来实现:
fs.mkdir('./fir/sec/thi',{recursive:true},err => {if(err){console.log('创建失败');return;}console.log('创建成功');
})
recursive表示递归。这样我们就能实现递归创建文件夹了。
2、文件夹读取
我们使用readdir来进行对文件夹的读取:
const fs = require('fs');fs.readdir('../test',(err,data)=>{if(err){console.log('读取失败');return;}console.log(data);
})
返回的结果是一个数组,数组中的元素为文件夹中文件的名称。
3、删除文件夹
删除我们使用rmdir方法。使用方法与读取相似。来看代码:
const fs = require('fs');
fs.rmdir('./draft',err => {if(err){console.log('删除失败');return;}console.log('删除成功');
})
//递归删除
fs.rmdir('./fir/sec',{recursive:true},err => {if(err){console.log('删除失败');return;}console.log('删除成功');
})
运行后就能看到删除成功了。目录仍然使用之前的目录。
查看资源状态
使用fs模块查看资源状态时需要用到方法 stat 。它具有三个参数:path、option和callback。
使用方法也很简单。直接上代码:
const fs = require('fs');
fs.stat('../test/test2.txt',(err,data) => {if(err){console.log('查看失败');return;}console.log(data);
})
运行后能看到指定文件的各种信息:
文件的信息我们介绍一些:
- size:查看文件的大小
- birthtimeMs:文件的创建时间
- atimeMs:文件最后的访问时间
- mtimeMs:文件最后的修改时间
- ctimeMs:文件最后的状态修改时间
此外,我们还可以使用 ifFile 来检测目标资源是否是一个文件;用 isDirectory来检测目标资源是否是一个文件夹。
path模块
最后我们来介绍一个相关的path模块。path模块提供了操作路径的功能,我们学习以下常用的一些API:
- path.resolve:拼接规范的绝对路径
- path.sep:获取操作系统的路径分割符
- path.parse:解析路并返回对象
- path.basename:获取路径的基础名称
- path.dirname:获取路径的目录名
- path.extname:获得路径的扩展名