Node.js核心API(fs篇)
前言:
在Node.js生态系统中,文件系统操作是后端开发不可或缺的一部分。fs模块作为Node.js核心API的重要组成部分,提供了与文件系统交互的能力,涵盖了从基础的文件读写到复杂的目录操作等功能。
现代JavaScript开发中,处理本地文件是常见需求,无论是配置文件读取、日志记录还是数据持久化存储。fs模块通过同步和异步两种方式提供这些功能,适应不同场景的性能要求。
随着Node.js版本的迭代,fs模块不断加入新的特性,如Promise-based API的引入,使得文件操作能够更好地融入现代异步编程模式。理解并掌握fs模块,对于构建健壮的Node.js应用具有重要意义。
本部分内容将深入解析fs模块的核心功能,包括常用方法的原理和使用场景,帮助开发者高效安全地处理文件系统操作,为构建复杂应用打下坚实基础。
1.读取文件
1.同步
使用readFileSync方法,它的写法简洁,但会阻塞后面的代码执行,基本代码如下:
const fs = require('fs')// 同步写法 会阻塞后面代码执行
const read = fs.readFileSync('./a.txt', 'utf8')
console.log(read)
在终端中使用 node 文件名 将内容打印出来
readFileSync('需要读取文件的文件名', '编码')
2.异步
使用readFile方法,它接收三个参数,第一个是需要读取文件的文件名,第二个参数可以接受一个对象,可以在里面设置一些行为,就比如说设置读取到文字的编码,第三个参数接受一个回调函数,基本的写法如下:
const fs = require('fs')// 异步
fs.readFile('./a.txt', {encoding: 'utf8', // 编码flag: 'r' // 读取
}, (err, data) => {if (err) throw err // 将错误抛出console.log(data)
})
3.promise
这种写法就可以通过.then或.catch来处理成功或失败的结果,我个人还是推荐使用这种写法。代码如下:
const fs = require('fs/promises')// promise
fs.readFile('./a.txt').then(result => {console.log(result.toString('utf8'));
}).catch(err => {throw err
}).finally(()=>{console.log('不管成功与否我都执行');
})
看到这可能有些人有点蒙,为什么编码有这么多种写法,其实这三种都是可以的,看个人习惯,以及需求。
4.可读流
在处理大文件时会使用到可读流,它会将文件里的内容一点一点传过来,假设有一个很大内存的文件,不可能使用readFile一直等着,代码如下:
const fs = require('fs')// 可读流 处理大文件
const readStream = fs.createReadStream('./a.txt')readStream.on('data', chunk => {console.log(chunk.toString())
})readStream.on('end', () => {console.log('读取完成了')
})
2.创建文件夹
使用到了mkdirSync,一般都是同步的,因为创建一个文件夹的速度是非常快的。代码如下:
const fs = require('fs')// 创建文件夹
fs.mkdirSync('./a')
如果需要创建一个嵌套的文件夹,会发现比如将路径改为./a/b/c,这样是不行的,那如何创建呢,可以使用递归,当然不用我们直接写,只需要添加第二个参数即可,代码如下:
const fs = require('fs')// 创建嵌套文件夹
fs.mkdirSync('./a/b/c', {recursive: true
})
3.删除
这个比较简单,使用rm方法,命名跟Linux差不多。代码如下:
const fs = require('fs')// 删除
fs.rmSync('./a', {recursive: true
})
如果是嵌套的文件夹,只需要递归删除即可。
4.重命名
const fs = require('fs')// 重命名
fs.renameSync('./a.txt', './b.txt')
第一个参收是需要重命名文件名称,第二个参数是要修改的名称。
5.监听文件的变化
使用watch方法,许多热更新的底层原来就用到了这个。代码如下:
const fs = require('fs')// 监听文件的变化
fs.watch('./a.txt', (event, filename) => {console.log(event, filename);
})
当我修改a.txt中的内容时,这个事件就会触发
6.写入文件
使用writeFile或writeFileSync方法,代码如下:
const fs = require('fs')// 写入文件
fs.writeFileSync('./a.txt', '666')
当运行脚本会发现,它会将原来文本里面的内容替换成我们写入的内容,而不是追加,接下来就来说追加的操作。
7.追加写入文件
1.第一种方法(writeFileSync)
写入的方法也有追加的功能,添加第三个参数,代码如下:
const fs = require('fs')// 追加文件
fs.writeFileSync('./a.txt', '\n777', {flag: 'a'
})
a的意思是append追加的意思
2.第二种方法(appendFileSync)
const fs = require('fs')// 追加文件
fs.appendFileSync('./a.txt', '\n888')
8.可写流
从名字可以看出和可读流类似,可以回顾一下可读流的意思就可以大致猜到可写流是什么意思。
可写流的意思就是将大量的数据分批插入。
const fs = require('fs')// 可写流const writeStream = fs.createWriteStream('./a.txt')const data = ["青山衔落日,","碧水映霞飞。","风过荷香漫,","蝉鸣暮色微。","孤舟横野渡,","倦鸟宿林扉。","欲寄乡思远,","星河入梦归。"
]data.forEach(item => {writeStream.write(item + '\n')
})// 记得关闭 不然通道一直打开
writeStream.end()// 也可以添加事件 就比如通知写入完成
writeStream.on('finish',() => {console.log('写入完成');
})
结语:
Node.js的fs模块为开发者提供了强大而灵活的文件系统操作能力,覆盖从基础读写到高级流处理的各类场景。通过同步、异步和Promise三种模式,开发者可根据项目需求选择最佳实践方式,平衡代码可读性与性能要求。
文件流处理技术(可读流/可写流)尤其适合大文件操作场景,有效避免内存压力。目录创建与删除的递归选项、文件监听机制等特性,为构建自动化工具和实时系统提供了底层支持。
现代JavaScript开发中,建议优先考虑Promise-based API或异步模式,结合错误处理机制构建健壮的应用。掌握这些核心方法后,开发者可以高效实现配置文件管理、日志系统、数据持久化等关键功能,为复杂Node.js应用奠定坚实基础。