创建一个文件写入流

fs.createWriteStream(path[, options])

可选填参数

image.png

写入

ws.write(data)

返回值与背压问题

image.png
当返回值为true说明管道内还可以添加数据,当为false时说明管道已经满啦, 管道的值由highWaterMark 来规定 ,然而内存处理数据的速度非常快,而硬盘写入速度又慢, 内存会将数据按照highWaterMark 的值将数据分组放进队列等待写入成功,放入一组字节。这样就会产生背压,这样就会浪费内存的储存空间,毕竟内存的储存空间本来就不多。
如图
image.png

示例:

  1. const path = require('path');
  2. const fs = require('fs');
  3. const firName = path.resolve(__dirname, './a.txt');
  4. const ws = fs.createWriteStream(firName,{
  5. flags: 'w',
  6. encoding: 'utf-8',
  7. highWaterMark: 16 * 1024,
  8. autoClose: true,
  9. })
  10. /**
  11. * 写入
  12. * 背压问题
  13. * 由于highWaterMark规定啦每次操作的字节数,当达到规定的字节数就开始写入,写入成功才会执行下次写入
  14. * 由于内存处理数据能比硬盘强,故内存会将需要写入的数据进行排队,以highWaterMark规定的字节数为一组
  15. * 而内存中的空间是有限且内空间珍贵,这样会导致背压问题,内存中滞留的啦数据,
  16. */
  17. const flag = ws.write('aaaa');
  18. console.log(flag)
  19. //当写入队列清空时,会触发drain事件
  20. ws.on('drain', () => {
  21. console.log('写入成功,管道已经清空可以开始写入啦')
  22. })

解决背压

背压问题就是管道满啦,内存还在处理数据,我们可以在管道满时停止处理数据
当管被清空时在让内存处理数据
可以使用事件drain

drain事件

当写入队列清空时,会触发drain事件
这个事件会在每次写入队列清空时触发,也就是硬盘写入成功触发
示例:

  1. /**
  2. * 解决背压问题
  3. * 判断flag,当满足与highWaterMark固定值,flag就会变为flase 此时就暂停写入
  4. * 当管道清空说明写入成功,恢复写入
  5. */
  6. let i = 0;
  7. function test () {
  8. let flag = true;
  9. while(i < 1024*1024 && flag) {
  10. flag = ws.write('a')
  11. i++;
  12. }
  13. }
  14. test()
  15. ws.on('drain', () => {
  16. console.log('drain')
  17. test()
  18. })

简单做法- pipe(写入流)

读取流中有一个方法 pipe
可以实现读取一点写入一点
代码:

  1. const fs = require('fs')
  2. const patn = require('path')
  3. const readF = patn.resolve(__dirname, './a.txt')
  4. const writeF = patn.resolve(__dirname, './b.txt');
  5. const rs = fs.createReadStream(readF, {
  6. encoding: 'utf8'
  7. })
  8. const ws = fs.createWriteStream(writeF)
  9. /**
  10. * 解决背压, 读一点写一点
  11. */
  12. rs.pipe(ws)
  13. rs.on('close', () => {
  14. console.log('close')
  15. })