前言
文件流 文件的读取和操作
readFile 、writeFile 缺陷 :会淹没内存 所以可以变成=> read+write(open、read、close) 读一点写一点,但是这样又太复杂 fs自己封装了fs.createReadStream
fs.createReadStream
概念
这里先创建一个文件1.txt
1 | 12345678909 |
1 | const fs = require('fs'); |
- 可读流需要掌握的方法 ‘data’ ‘end’ Buffer.concat()
1.txt
1 | 你好 |
1 | const fs = require('fs'); |
手写可读流原理
1】
新建:调用文件 stream.js 原理 ReadStream.js
1 | // stream.js |
对ReadStream.js
分析:rs这个实例是有on
方法,并且这里上面line17 rs.on('data')
时能够读取文件,所以我需要下面line21能够监听到on('data')
这个事件, 所以这里继承 events
,因为它有 'newListener'
可以监听到 'data'
,同样的这个实例上也就有on ('newListener')
方法 如line21,所以这里 ReadStream extends Events
1 | // ReadStream.js |
结果分析:从打印结果可以看出,虽然line19先执行的是open,但是line35 执行的是异步,而stream.js line17这里又绑了data,就会马上触发line21,只要stream.js里面的on绑定了事件(此刻是’data‘),就会立刻触发’newListener‘,这里面是同步的,也就执行了line29read()方法
2】
现在希望先open执行完再执行read
1 | // stream.js |
1 | // ReadStream.js |
分析:
- 顺序:
stream.js
line5一new这个类,立马line18执行open事件,因为line38是异步执行,所以在line41emit的时候,stream.js
的line14 open已经绑定好了,所以能够触发 并且把fd也能传过去 - 这里用发布订阅的思想来解耦
1
2
3
4
5
6
7
8
9
10
11
12// 之前的相当于如下:
fs.open(path,..,function(){ // 成功之后再read
fs.read(...console.)
})
// 现在就相当于
fs.open(...,function(){
rs.emit('ok');
})
this.on('ok',function() {
rs.read(...);
})
// 让两个相关联的异步解耦并且是有关联的
3】
读取到内容
1 | // stream.js |
1 | // ReadStream.js |
问题: 现在可以看到 1.txt里面的 你好 占6个字节 现在将左侧 stream.js
的line12 end改成4,这样从0-4就是读取5个 运行可以看到结果还是读取了6个 因为line37读取的是this.highWaterMark;如果使用原生的则是读取5个
4】
howMuchToRead 、close()
1 | // stream.js |
1 | // ReadStream.js |
5】
pause() 、resume()
1 | // 这里引用原生 fs.createReadStream |
引用改成自己手写的ReadStream
this.flowing
1 | // stream.js |
1 | // ReadStream.js |
可读流
- 如何将多个 有关系的异步代码进行拆分 read() open() 发布订阅
可写流
- 如何处理并发操作文件 多个异步 造队列 => 链表