梦入琼楼寒有月,行过石树冻无烟

Node stream

流(Stream)是一种传输手段,其核心含义是指一个有始有终的数据传输结构,这通常是文件打开 -> 关闭的过程,在 Node.js 中分为四个基本的流类型,分别为:

Id Name Info
1 Writable 可写入流(fs.createWriteStream()
2 Readable 读取流 (fs.createReadStream())
4 Duplex 可读流 (net.Socket)
4 Transorm 在读写的过程中可以修改和变换数据的可读写流(Duplex,zlib.createDeflate()

对于体积较大的二进制文件,如音频、视频文件或以 GB 为单位来衡量大小的,则会容易造成 爆仓 ,为避免爆仓的发生,读取体积大的文件应使用读一部分写一部分的方式进行。

Readable

对于 node 的可读取留,即通过 fs.createReadStream 方法创建一个读取流,其参数大多数可通过 Node.js File System 进行参考,在这其中 highWaterMark 参数主要的作用是内部读取缓存区大小,这将在某些情况下,需要触发底层可读留机制的刷新,从而不消耗任何数据。

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
32
33
34
35
36
37
38
39
40
41
42
43
const fs = require('fs')

/*
Stream in open
file data => This is desfile.txt
Stream in end
Stream in close
*/
var rs = fs.createReadStream('desfile.txt',{
flags: 'r',
mode: 0o666, // https://www.xuchao.org/docs/freebsd/permissions.html
encoding: 'utf-8',
start: 0,
end: 19,
highWaterMark: 1
})

rs.on('open', function () {
console.log('Stream in open')
})

rs.setEncoding('utf-8')

// 将可读流传出 data 事件
rs.on('data', function (data) {
console.log('file data => ',data)
rs.pause() // 切出流模式
setTimeout(function () {
rs.resume() // 恢复流模式
}, 2000)
})

rs.on('error', function () {
console.log('Stream in error')
})

rs.on('end', function () {
console.log('Stream in end')
})

rs.on('close', function () {
console.log('Stream in close')
})

之后根据其 Stream 流程 open -> data -> error -> end -> close ,其中在监听 data 事件中,就可读取文件的内容并输出数据,边度边输的模式,这将会不停的通过 data 读取数据、触发 data 后再次读取。

在这个过程中主要的不是将文件的整体内容读取并输出,而是通过 fs.createReadStream 方法所设置的缓存区,大小默认为 64KB(这可通过 highWaterMark 参数进行设置)

Writable

可写流(Writable Stream),主要通过使用 fs.createWriteStream() 方法进行创建,并通过 ws.write 进行写入,并当 end 事件后后使用 finish 事件来回调方法。

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
const fs = require('fs')
var ws = fs.createWriteStream('desfile.txt', {
flags: 'w',
mode: 0o666,
start: 0,
highWaterMark: 1
})

// 打开流
ws.on('open', function () {
console.log('Stream in open')
})

// 写入流
ws.write('hey,fs.createWriteStream()','utf-8')

// 关闭流
ws.on('close', function () {
console.log('Stream in close')
})

// 结束流
ws.end()

// 当 end 事件后且以刷新所有底层系统,则触发回调
ws.on('finish', function () {
console.log('Stream in end')
})

管道流

管道流提供了一个输出和输入流的机制,这最为常用到的场景就是获取一个流的数据并写入另一个流当中。

1
2
3
4
5
6
7
const fs = require('fs')
var rs = fs.createReadStream('befile.txt')
var ws = fs.createWriteStream('desfile.txt')

rs.on('data', function (chunk) {
ws.write(chunk)
})

或者通过其 rs.pipe() 方法,将可读流写到可写流当中,并触发 pipe 事件:

1
2
3
4
5
6
7
const fs = require('fs')
var rs = fs.createReadStream('befile.txt')
var ws = fs.createWriteStream('desfile.txt')

rs.on('data', function (chunk) {
ws.write(chunk)
})
⬅️ Go back