本地文件操作模块 fs
fs 模块对文件的操作有异步和同步两种方式,例如:readFile() 和 readFileSync()
区别:
- 同步调用会阻塞代码的执行,异步不会
- 异步调用会将读取任务下达到任务队列,知道任务执行完成才会回调
- 异常处理:同步必须要使用 try catch 方式,异步可以使用回调函数的第一个参数 err 【重要】
文件读取
方法 |
说明 |
readFile |
异步读取 |
readFileSync |
同步读取 |
createReadStream |
流式读取 |
| const fs = require('fs') |
| |
| |
| const data |
| |
| try{ |
| data = fs.readFileSync('./file1.txt','utf8') |
| console.log(data) |
| } catch(err) { |
| console.error('读取文件错误:' + err.message) |
| } |
| |
| |
| 文件内容:Hello World! |
| |
| |
| fs.readFile('./file1.txt','utf8',(err, dataStr) => { |
| if(err) return console.log('读取文件错误:' + err.message) |
| console.error(dataStr) |
| }) |
| |
| |
| 文件内容:Hello World! |
从 Node.js 14 开始,fs 模块提供了两种使用基于 promises 的文件系统的方法。这些 promises 可以通过 require('fs').promises
或 require('fs/promises')
获得
| import { readFile } from 'fs/promises'; |
| |
| try { |
| const contents = await readFile(filePath, { encoding: 'utf8' }); |
| console.log(contents); |
| } catch (err) { |
| console.error(err.message); |
| } |
流式
| const fs = require('fs') |
| |
| let rs = fs.createReadStream(__dirname + '/grades.txt') |
| |
| rs.on('data', chunk => { |
| console.log(chunk, chunk.length) |
| }) |
| rs.on('end', () => console.log('ok')) |
文件写入
方法 |
说明 |
writeFile |
异步写入 |
writeFileSync |
同步写入 |
appendFile / appendFileSync |
追加写入 |
createWriteStream |
流式写入 |
如果文件不存在,则创建文件,如果文件存在,则覆盖文件内容
| const fs = require('fs'); |
| |
| fs.writeFile('./fileWrite.txt', 'hello world', 'utf8', function(err){ |
| if(err) throw err; |
| console.log('文件写入成功'); |
| }); |
| |
| try{ |
| fs.writeFileSync('./fileForWrite1.txt', 'hello world', 'utf8'); |
| console.log('文件写入成功'); |
| }catch(err){ |
| throw err; |
| } |
追加写入
| |
| fs.append('./grades.txt', 'hello world', err =>{ |
| if(err) throw err |
| console.log('追加成功') |
| }) |
| |
| |
| fs.appendFileSync('./grades.txt','\r\nHello World') |
promises
| import { writeFile } from 'fs/promises'; |
| |
| try { |
| const contents = await writeFile('message.txt', 'hello world', { encoding: 'utf8' }); |
| console.log(contents); |
| } catch (err) { |
| console.error(err); |
| } |
流式写入
| let ws = fs.createWriteStream('./观书有感.txt') |
| |
| |
| ws.write('半亩方塘一鉴开\r\n') |
| ws.write('天光云影共徘徊\r\n') |
| ws.write('问渠那得清如许\r\n') |
| ws.write('为有源头活水来\r\n') |
| |
| |
| ws.end() |
程序打开一个文件是需要消耗资源的,流式写入可以减少打开关闭文件的次数
流式写入是用于大文件写入或者频繁写入的场景,writeFile 适合写入频繁较低的场景
文件读写小案例
| |
| 小王=100,小李=90,小陈=30,小高=80,小胖=99 |
| |
| |
| const fs = require('fs') |
| |
| fs.readFile(__dirname + '/grades.txt', 'utf8', (err, dataSrc) => { |
| if (err) return console.log('文件读取错误' + err) |
| const oldArr = dataSrc.split(',') |
| let newArr = [] |
| oldArr.forEach(item => { |
| newArr.push(item.replace('=', ':')) |
| }) |
| const newStr = newArr.join('\r\n') |
| |
| fs.writeFile(__dirname + '/grades-ok.txt', newStr, { encoding: 'utf8', flag: 'a' }, function (err) { if (err) return console.log('文件写入错误' + err) }) |
| }) |
| |
| |
| 小王:100 |
| 小李:90 |
| 小陈:30 |
| 小高:80 |
| 小胖:99 |
文件移动与重命名
| |
| fs.rename('./old.txt', './new/new.txt', err =>{ |
| if(err) throw err |
| console.log('移动完成') |
| }) |
| |
| fs.renameSync('./old.txt', './new/new.txt') |
注意:如果还是移动到当前路径,但是修改了名字,就是重命名
文件删除
| const fs = require('fs') |
| |
| |
| fs.unlink('./test.txt', err => { |
| if(err) thorw err |
| console.log('删除成功') |
| }) |
| |
| |
| fs.unlinkSync('./test.txt') |
| |
| |
| |
| fs.rm('./test.txt', err => { |
| if (err) { |
| console.log('删除失败') |
| return |
| } |
| console.log('删除成功') |
| }) |
| |
| fs.rmSync('./test.txt') |
文件夹操作
方法 |
说明 |
mkdir / mkdirSync |
创建文件夹 |
readdir / readdirSync |
读取文件夹 |
rmdir / rmdirSync |
删除文件夹 |
mkdir 创建文件夹
| |
| fs.mkdir('./page',err => { |
| if(err) throw err |
| console.log('创建成功') |
| }) |
| |
| |
| fs.mkdir('./grandfather/father/son',{recursive: true},err => { |
| if(err) throw err |
| console.log('递归创建成功') |
| }) |
| |
| |
| fs.mkdirSync('./grandfather/father/son',{recursive: true}) |
注意:同步创建已存在文件夹会报错
readdir 读取文件夹
| |
| fs.readdir('./page', (err, data) => { |
| if(err) throw err |
| console.log(data) |
| }) |
| |
| let data = fs.readdirSync('./page') |
| console.log(data) |
| |
| |
| |
| const fs = require('fs') |
| const path = require('path') |
| |
| function readdirAll(dir){ |
| let results = [path.resolve(__dirname,dir)] |
| const files = fs.readdirSync(dir,'utf8') |
| files.forEach(file => { |
| file = path.resolve(dir,file) |
| const stats = fs.statSync(file) |
| if(stats.isFile()){ |
| results.push(file) |
| }else if(stats.isDirectory()){ |
| results = results.concat(readdirAll(file)) |
| } |
| }); |
| return results |
| } |
| |
| console.log(readdirAll('../')) |
| console.log(readdirAll('./')) |
rmdir 删除文件夹
| |
| fs.rmdir('./page',err=>{ |
| if(err) throw err |
| console.log('删除成功') |
| }) |
| |
| fs.rmdir('./page',{recursive: true},err=>{ |
| if(err) throw err |
| console.log('删除成功') |
| }) |
| |
| fs.rmdir('./page',{recursive: true}) |
| |
| |
| fs.rm('./page',{recursive: true},err=>{ |
| if(err) { |
| console.log(err) |
| return |
| } |
| console.log('删除成功') |
| }) |
获取文件夹状态
1.异步:fs.stat(path,callback):
path是一个表示路径的字符串,callback接收两个参数(err,stats),其中stats就是fs.stats的一个实例;
2.同步:fs.statSync(path)
只接收一个path变量,fs.statSync(path)其实是一个fs.stats的一个实例;
方法:
- stats.isFile():是否为文件
- stats.iisDirectory():是否为目录(文件夹)
| const fs = require('fs'); |
| |
| |
| statsObj = fs.statSync("test_file.txt"); |
| statsObj.isDirectory()); |
注意:上面遍历文件夹下的所有文件也是使用到了文件夹状态和两个方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具