nodeJS 写日志用writeFile还是appendFile

描述

我们知道作为后端,打 log 是一件很重要的事情,如果我们是用 NodeJs 作为后端的话,一般我们都会用第三方库来实现写日志,我又想到在 NodeJs 里头,好像有好几种写文件的方法,比如 fs.writeFilefs.appendFile,还有流的方式,那这几种方法有什么区别吗?

fs.writeFile

这个应该是我们开始接触 NodeJs 最早学习的 api 之一了吧,fs.write 有一个特点,就是 每次使用 writeFile 时,都会替换文件数据。由于他的这个特点,并且log 都是一条一条加的,所以这个方法不适合用来写 log
使用方法也很简单

// mock 的假 log
const genLogData = (method) => `${method}: new log-${new Date().getTime()}\n`;
fs.writeFile('./log.txt', genLogData('fs.writeFile'), 'utf8', () => {
  console.log('writeFile success')
})

缺点

每次使用 writeFile 时,都会替换文件数据

fs.readFile + fs.writeFile

单单只看 fs.writeFile,我们知道写他没法一条一条写入,但是可以和 fs.readFile 打个组合拳呀,fs.readFile 把文件内容给读出来,然后我在他内容拼接上,再一起写进去,不就行了吗?

// mock 的假 log
const genLogData = (method) => `${method}: new log-${new Date().getTime()}\n`;
fs.readFile('log.txt', { encoding: 'utf8' }, (err, data) => {
  // 拼接 log 日志
  const newData = data + genLogData('fs.readFile + fs.writeFile') + '\n';
  fs.writeFile('log.txt', newData, 'utf8', () => console.log('writeFile success'));
});

缺点

虽然这个方法可行,但是一看就知道性能不太好,要把文件全读出来,还有一次性全部写进去,如果文件打的话,性能可想而知。
fs.readFile 会把文件的内容加载的内存中,如果文件的内容非常大的时候,就有把内存给撑爆掉的风险。使用 fs.readFile 的小伙伴可要小心咯,别啥文件都用 fs.readFile 去读取

fs.appendFile

这个方法就好像是 fs.readFile + fs.writeFile 的简化版,并且它还不用把文件全部读出来,写的时候也在文件的尾部追加新的内容就好了。看起来真是个完美的解决方法。
代码也是非常的简单。

// mock 的假 log
const genLogData = (method) => `${method}: new log-${new Date().getTime()}\n`;
fs.appendFile('./log.txt', genLogData('fs.appendFile'), 'utf8', () => console.log('writeFile success'))

缺点

fs.appendFile 这个方法看起来很完美,但是它也是有缺点的,只是缺点可能没那么明显,有些人可能在实际生产中也不会发现。就是 fs.appendFile 在每次需要写日志时,都会打开一个文件句柄。在高并发的情况下会导致 EMFILE 错误,这是因为异步 I/O 会对文件系统进行大量并发调用,操作系统的文件描述符数量会瞬间被用光

fs.createWriteStream

说了那么多,有没有一个方法可以解决上面出现的这些缺点呢?就是 只追加文件新增的部分,并且不会打开文件的句柄。 有,那就是 fs.createWriteStream。通过 fs.createWriteStream 创建了一个可写流,并在日志来的时候以流的方式写入,不会将整个文件加载到内存中,每次程序写入文件时,不会创建新的文件描述符,可以避免 EMFILE 错误。

使用方法

const genLogData = (method) => `${method}: new log-${new Date().getTime()}\n`;
const log = fs.createWriteStream('log.txt', {flags: 'a'});
log.write(genLogData('fs.createWriteStream'))
log.end()

注意:使用后记得使用 end 方法结束流。

总结

NodeJS 还在强化中,感觉以前学的都很乱,直接上来就是 KoaExpress 这些框架,对 NodeJs 本身的了解还是很少的,只是一味的觉得不就是 Javascript 嘛,老子写了好几年了,是有点像,但是也不要被前端的思维框住了,不要带着前端的思维学习后端的知识。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值