stream(流)是什么?
流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface)。 stream
模块提供了基础的 API 。使用这些 API 可以很容易地来构建实现流接口的对象。
Node.js 提供了多种流对象。 例如, HTTP 请求 和 process.stdout
就都是流的实例。
流可以是可读的、可写的,或是可读写的。所有的流都是 EventEmitter
的实例。
流是一种抽象的数据结构。想象水流,当在水管中流动时,就可以从某个地方(例如自来水厂)源源不断地到达另一个地方(比如你家的洗手池)。我们也可以把数据看成是数据流,比如你敲键盘的时候,就可以把每个字符依次连起来,看成字符流。
Node.js 中有四种基本的流类型:
- Readable - 可读的流 (例如
fs.createReadStream()
). - Writable - 可写的流 (例如
fs.createWriteStream()
). - Duplex - 可读写的流 (例如
net.Socket
). - Transform - 在读写过程中可以修改和变换数据的 Duplex 流 (例如
zlib.createDeflate()
).
所有使用 Node.js API 创建的流对象都只能操作 strings 和 Buffer
(或 Uint8Array
) 对象。但是,通过一些第三方流的实现,你依然能够处理其它类型的 JavaScript 值 (除了 null
,它在流处理中有特殊意义)。 这些流被认为是工作在 “对象模式”(object mode)。
Readable (可读流)
Readable 事件:
readable:事件将在流中有数据可供读取时触发。在某些情况下,为 'readable'
事件添加回调将会导致一些数据被读取到内部缓存中。
data:事件会在流将数据传递给消费者时触发。当流转换到 flowing 模式时会触发该事件。调用 readable.pipe()
, readable.resume()
方法,或为 'data'
事件添加回调可以将流转换到 flowing 模式。 'data'
事件也会在调用 readable.read()
方法并有数据返回时触发。
end: 事件将在流中再没有数据可供消费时触发。
close: 当底层资源,如文件,已关闭时触出。
error:在接收数据中出错是触发。
Readable 方法:
read([size]):从流中读数据.数据可以是String、Buffer、null(下面代码会有),当指定size,那么只读仅限于那个字节数
setEncoding(encoding):设置read()请求读取返回String时使用的编码
pause():暂停从该对象发出的data事件
resume():恢复从该对象发出的data事件
创建一个Readable(可读流):
let fs = require('fs');let path = require('path');
// 返回的是一个可读流对象let rs = fs.createReadStream(path.join(__dirname,'1.txt'),{ flags:'r', // 文件的操作是读取操作 encoding:'utf8', // 默认是null null代表的是buffer autoClose:true, // 读取完毕后自动关闭 highWaterMark:3,// 默认是64k 64*1024b 汉字是三个字节 start:0, // 123 456 789 //end:9 // 包前又包后});// 默认情况下 不会将文件中的内容输出// 内部会先创建一个buffer先读取3b
// 流动模式会疯狂的触发data事件,直到读取完毕//rs.setEncoding('utf8');rs.on('open',function(){ console.log('文件打开了')});// newLisenterrs.on('data',function(data){ // 暂停模式 -> 流动模式 console.log(data); // rs.pause(); // 暂停方法 表示暂停读取,暂停data事件触发});
rs.on('readable',function(res){ console.log('有数据了'); });rs.on('error',function(err){ console.log(err);});rs.on('end',function(){ console.log('end')});rs.on('close',function(){ console.log('关闭')});复制代码
输出的:
文件打开了 0123456789 有数据了 end 关闭复制代码
Writable (可写流)
Writable事件:
write(chunk,[encoding],[callback]):将数据写入流。chunk(数据块)中包含要写入的数据,encoding指定字符串的编码,callback指定当数据已经完全刷新时执行的一个回调函数。如果成功写入,write()返回true.
end([chunk],[encoding],[callback]):与write()相同,它把Writable对象设为不再接受数据的状态,并发送finish事件。
Writable方法:
drain:在write()调用返回false后,当准备好开始写更多数据时,发出此事件通知监视器。
finish:当end()在Writable对象上调用,所以数据被刷新,并不会有更多的数据被接受时触发
创建一个Writable:
let fs = require('fs');let path = require('path');
// 写的时候文件不存在 会创建文件let ws = fs.createWriteStream(path.join(__dirname,'1.txt'),{ highWaterMark:3, autoClose:true, flags:'w', encoding:'utf8', mode:0o666, start:0,});// 写内容的时候 必须是字符串或者bufferfor(var i = 0;i<4;i++){ let flag = ws.write(i+''); // 第一次写一个字符 console.log(flag)}ws.on('drain',function(){ console.log('drain')});复制代码
控制台打印:
true true false falsedrain1.txt 的内容是: 0123复制代码