fs 模块
fs 全称为
file system
,称之为文件系统
,是 Node.js 中的内置模块
,可以对计算机中的磁盘进行操作。
本章节会介绍如下几个操作:
- 文件写入
- 文件读取
- 文件移动与重命名
- 文件删除
- 文件夹操作
- 查看资源状态
文件写入
文件写入就是将 数据 保存到 文件 中,我们可以使用如下几个方法来实现该效果
方法 | 说明 |
---|---|
writeFile | 异步写入 |
writeFileSync | 同步写入 |
appendFile / appendFileSync | 追加写入 |
createWriteStream | 流式写入 |
writeFile 异步写入
语法: fs.writeFile(file, data[, options], callback)
参数说明:
- file 文件名
- data 待写入的数据
- options 选项设置
(可选)
- callback 写入回调
返回值: undefined
代码示例:
// require 是 Node.js 环境中的 '全局' 变量,用来导入模块
const fs = require('fs')// 将 [三人行,必有我师焉。] 写入到当前文件夹下的 [座右铭.txt] 文件中
fs.writeFile('./座右铭.txt', '三人行,必有我师焉。', err =>{// 如果写入失败,则回调函数调用时,会传入错误对象,如写入成功,会传入 nullif(err){console.log(err)return}console.log('写入成功')
})
writeFileSync 同步写入
语法: fs.writeFileSync(file, data[, options])
参数与 fs.writeFile
大体一致,只是没有 callback 参数
返回值:undefined
代码示例:
try{fs.writeFileSync('./座右铭.txt', '三人行,必有我师焉。')
}catch(e){console.log(e)
}
Node.js 中的磁盘操作是由其他
线程
完成的,结果的处理有两种模式:
- 同步处理 JavaScript 主线程
会等待
其线程的执行结果,然后再继续执行主线程的代码,效率较低
- 异步处理 JavaScript 主线程
不会等待
其线程的执行结果,直接执行后续的主线程代码,效率较好
appendFile / appendFileSync 追加写入
appendFile
作用是在文件尾部追加内容,appendFile
语法与writeFile
语法完全相同
语法:
fs.appendFile(file, data[, options], callback)
fs.appendFileSync(file, data[, options])
返回值:二者都为 undefined
实例代码:
fs.append('./座右铭.txt', '则其善者而从之,其不善者而改之。', err =>{if(err) throw errconsole.log('追加成功')
})fs.appendFileSync('./座右铭.txt','\r\n温故而知新,可以为师矣')
createWriteStream 流式写入
语法:fs.createWriteStream(path[, options])
参数说明:
path
文件路径options
选项配置(可选
)
**返回值: **Object
代码示例:
let ws = fs.createWriteStream('./观书有感.txt')//写入数据到流
ws.write('半亩方塘一鉴开\r\n')
ws.write('天光云影共徘徊\r\n')
ws.write('问渠那得清如许\r\n')
ws.write('为有源头活水来\r\n')//关闭写入流,表明已没有数据要被写入可写流
ws.end()
程序打开一个文件是需要消耗资源的,流式写入可以减少打开关闭文件的次数。
流式写入方式适用于 大文件写入或者频繁写入的场景,
writeFile
适合于 写入频率较低的场景
写入文件的场景
文件写入
在计算机中是一个非常常见的操作,下面的场景都用到了文件写入
- 下载文件
- 安装软件
- 保存程序日志,如 Git
- 编辑器保存文件
- 视频录制
当 需要持久化保存数据 的时候,应该想到
文件写入
文件读取
文件读取顾名思义,就是通过程序从文件中取出其中的数据,我们可以使用如下几种方式:
方法 | 说明 |
---|---|
readFile | 异步读取 |
readFileSync | 同步读取 |
createReadStream | 流式读取 |
readFile 异步读取
语法: fs.readFile(path[, options], callback)
参数说明:
- path 文件路径
- options 选项配置
- callback 回调函数
返 回 值 : undefined
代码示例:
// 导入 fs 模块fs.readFile('./座右铭.txt', (error,data) =>{if(err) throw errconsole.log(data)
})fs.readFile('./座右铭.txt', 'uft-8', (error,data) =>{if(err) throw errconsole.log(data)
})
readFileSync 同步读取
语法:fs.readFileSync(path[, options])
参数说明:
- path 文件路径
- options 选项配置
返 回 值 :string | Buffer
代码示例:
let data = fs.readFileSync('./座右铭.txt')
let data = fs.readFileSync('./座右铭.txt', 'utf-8')
createReadStream 流式读取
语法:fs.createReadStream(path[, options])
参数说明:
- path 文件路径
- options 选项配置(
可选
)
返回值:Object
代码示例:
// 创建读取流对象
let rs = fs.createReadStream('./观书有感.txt')// 每次取出 64k 数据后执行一次 data 回调
// 绑定一个 data 事件 chunk 块儿 大块儿
re.on('data', chunk =>{console.log(chunk)console.log(chunk.length)
})// 读取完毕后,执行 end 回调 (可选事件)
re.on('end', () =>{console.log('读取完毕')
})
读取文件应用场景
- 电脑开机
- 程序运行
- 编辑器打开文件
- 查看图片
- 播放视频
- 播放音乐
- Git 查看日志
- 上传文件
- 查看聊天记录
文件移动与重命名
在 Node.js 中,我们可以使用
rename
或renameSync
来移动或重命名文件或文件夹
语法:
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)
参数说明:
- oldPath 文件当前的路径
- newPath 文件新的路径
- callback 操作后的回调
代码示例:
fs.rename('./观书有感.txt', './论语/观书有感.txt', err =>{if(err) throw errconsole.log('移动完成')
})fs.renameSync('./座右铭.txt', './论语/.我的座右铭.txt')
注: 如果还是移动到当前路径,但是修改了名字,就是重命名了
文件删除
在 Node.js 中,我们可以使用
unlink
或unlinkSync
来删除文件
语法:
fs.unlink(path, callback)
fs.unlinkSync(path)
参数说明:
- path 文件路径
- callback 操作后的回调
代码示例:
const fs = require('fs')fs.unlink('./test.txt', err =>{if(err) throw errconsole.log('删除成功')
})fs.unlinkSync('./test2.txt')// 调用 rm 方法 14.4 同步 rmSync
fs.rm('./论语.txt', err => {if (err) {console.log('删除失败')return}console.log('删除成功')
})
文件夹操作
借助 Node.js 的能力,我们可以对文件夹进行
创建
、读取
、删除
等操作
方法 | 说明 |
---|---|
mkdir / mkdirSync | 创建文件夹 |
readdir / readdirSync | 读取文件夹 |
rmdir / rmdirSync | 删除文件夹 |
mkdir 创建文件夹
在 Node.js 中,我们可以使用
mkdir
或mkdirSync
来创建文件夹
语法:
fs.mkdir(path[, options], callback)
fs.mkdirSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置(
可选
) - callback 操作后的回调
示例代码:
// 异步创建文件夹 mk make 制作 dir directory 文件夹
fs.mkdir('./page', err =>{if(err) throw errconsole.log('创建成功')
})// 递归异步创建
fs.mkdir('./1/2/3', {recursive: true}, err =>{if(err) throw errconsole.log('递归创建成功')
})// 递归同步创建文件夹
fs.mkdirSync('./x/y/z', {recursive: true})
readdir 读取文件夹
在 Node.js 中,我们可以使用
readdir
或readdirSync
来读取文件夹
语法:
fs.readdir(path[, options], callback)
fs.readdirSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置(
可选
) - callback 操作后的回调
示例代码:
// 异步读取
fs.readdir('./论语', (err, data) => {if(err) throw errconsole.log(data)
})
// 同步读取
let data = fs.readdirSync('./论语')
console.log(data)
rmdir 删除文件夹
在 Node.js 中,我们可以使用
rmdir
或rmdirSync
来删除文件夹
语法:
fs.rmdir(path[, options], callback)
fs.redirSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置( 可选 )
- callback 操作后的回调
示例代码:
// 异步删除文件夹 rm remove 移除
fs.rmdir('./page', err => {if(err) throw errconsole.log('删除成功')
})
//异步递归删除文件夹 不推荐
//=>DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will be removed. Use fs.rm(path, { recursive: true }) instead
fs.rmdirSync('./1', {recursive: true}, err => {if(err){ console.log(err)return}console.log('递归删除')
})
//同步递归删除文件夹
fs.rmdirSync('./x', {recursive: true})// 建议使用
fs.rm('./a', { recursive: true }, err => {if (err) {console.log(err)return}console.log('删除成功')
})
查看资源状态
在 Node.js 中,我们可以使用
stat
或statSync
来查看资源的详细信息
语法:
fs.stat(path[, options], callback)
fs.statSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置( 可选 )
- callback 操作后的回调
示例代码:
// 异步获取状态
// stat 方法 status 缩写 状态
fs.stat('/data.txt', (err, data) =>{if(err) throw errconsole.log(data)
})
// 同步获取状态
let data = fs.statSync('./data.txt')
结果值对象结构:
- size 文件体积
- birthtime 创建时间
- mtime 最后修改时间
- isFile 检测是否为文件
- isDirectory 检测是否为文件夹
- …
相对路径问题
fs 模块对资源进行操作时,路径的写法有两种:
- 相对路径
./座右铭.txt
当前目录下的 座右铭.txt座右铭.txt
等效于上面的写法../座右铭.txt
当前目录的上一级目录中的 座右铭.txt
- 绝对路径
D:/Program Files
windows 系统下的绝对路径/user/bin
Linux 系统下的绝对路径
相对路径中所谓的
当前目录
,指的是命名行的工作目录
,而并非是文件的所在目录所以当命名行的工作目录与文件所在目录不一致时,会出现一些 Bug
__dirname
__dirname
与 require
类似,都是 Node.js 环境中的 ‘全局’ 变量
__dirname
保存着 当前文件夹所在目录的绝对路径,可以使用 __dirname
与文件名拼接成绝对路径
代码示例:
//=>__dirname + '/data.txt' === 'D:\\Desktop\\Node\\code\\03-fs模块/data.txt'
let data = fs.readFileSync(__dirname + '/data.txt')
console.log(data)
使用 fs 模块的时候,尽量使用
__dirname
路径转换为绝对路径,这样可以避免相对路径产生的 Bug
练习
编写一个 JS 文件,实现复制文件的功能
/* * 需求:* 复制 资料文件夹下的 [笑看风云.mp4]*/
// 导入 fs 模块
const fs = require('fs')
// 方式一 readFile
// 读取文件内容
let data = fs.readFileSync('./资料/笑看风云.mp4')
// 写入文件
fs.writeFileSync('./资料/笑看风云2.mp4', data)// 方式二 流式操作
// 创建读取流对象
const rs = fs.createReadStream('./资料/笑看风云.mp4')
// 创建一个写入流对象
const ws = fs.createWriteStream('./资料/笑看风云3.mp4')// 绑定data事件
// 理想状态下,读取 64k 就写入 64 k,这样消耗的内存最少,实际上读取的速度大于写入的速度
rs.on('data', chunk => {ws.write(chunk)
})
// 绑定data事件 ==== rs.pipe(ws)
文件重命名
// 1. 导入 fs 模块
const fs = require('fs')// 读取 03-fs模块 文件夹
const files = fs.readdirSync('../03-fs模块')// 遍历数组
files.forEach(item => {// 判断let [num, name] = item.split('-')if (num < 10) {num = '0' + num}// 创建新的文件名let newName = num + '-' + name// 重命名fs.renameSync(`../03-fs模块/${item}`, `../03-fs模块/${newName}`)
})