Stream

流 (Stream)

___流:

  • 是连续字节的一种表现形式和抽象概念
  • 流应该是可读的,也是可写的

我们之前可以通过readFile或者write File的方式读写文件 为什么还需要流?

  • 因为直接读写文件的方式,虽然简单,但是无法控制一些细节的操作
  • 比如从什么位置开始读、读到什么位置、一次性读取多少个字节
  • 读到某个位置后,暂停读取,某个时刻恢复读取等等;
  • 或者这个文件非常大,比如一个视频文件,一次性全部读取并不合适;

文件读写的Stream

事实上Node中很多对象是基于流实现的:

  • http模块的Request和Response对象;

  • process.stdout对象;

  • 所有的流都是EventEmitter的实例

Node.js中有四种基本流类型:

  • Writable:可以向其写入数据的流(例如 fs.createWriteStream())。
  • Readable:可以从中读取数据的流(例如 fs.createReadStream())。
  • Duplex:同时为Readable和的流Writable(例如 net.Socket)。
  • Transform:Duplex可以在写入和读取数据时修改或转换数据的流(例如zlib.createDeflate())。

Readable

传统读取文件信息:

1
2
3
fs.readFile('./foo.txt',(err,data)=>{
console.log(data);
})

流的方式读取

1
2
3
4
5
const reader = fs.createReadStream("./foo.txt",{
start: 3, //文件读取开始的位置
end: 10, //end:文件读取结束的位置;
highWaterMark: 2 //highWaterMark:一次性读取字节的长度,默认是64kb
})

通过监听data事件 获取读到的数据:

1
2
3
4
5
6
7
reader.on('data',(data)=>{
console.log(data);
reader.pause(); //暂停
setTimeout(() => {
reader.resume() //恢复
}, 2000)
})

文件打开关闭:

1
2
3
4
5
6
reader.on('open',()=>{
console.log("文件被打开");
})
reader.on('close',()=>{
console.log("文件被关闭");
})

Writeable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//传统写入方式
// fs.writeFile('./bar.txt',"hello Write",(err)=>{
// console.log(err);
// })

//Stream的写入方式
const writer =fs.createWriteStream('./bar.txt',{
flags: "r+", //在windows电脑上要用r+ 在对应位置写入 而不用a
start: 1
})

writer.write("hea",(err)=>{
if(err){
console.log(err);
return
}
console.log("写入成功");
})
writer.write("voc",(err)=>{
console.log("第二次写入");
})

// writer.close()

//write("Hello Woe")
//close()
writer.end("Hello Woe")

writer.on('close',()=>{
console.log("文件被关闭");
})

pipe方法

1
2
3
4
5
6
7
8
9
10
11
12
13
//传统写法
fs.readFile('./bar.txt',(err,data)=>{
fs.writeFile('./baz.txt',data,(error)=>{
console.log(error);
})
})

//Stream写法
const reader = fs.createReadStream('./foo.txt')
const writer = fs.createWriteStream('./foz.txt')

reader.pipe(writer)
writer.close()