Node.js数据流Stream之Readable流和Writable流

一、前传

Stream在很多语言都会有,当然Node.js也不例外。数据流是可读、可写、或即可读又可写的内存结构。Node.js中主要包括Readable、Writable、Duplex(双工)和Transform(变换)流。但是在学这些之前先学会util模块中的一个从其他对象继承的功能.

util模块提供了util.inherits()方法来允许你创建一个继承另一个对象的prototype(原形)方法的对象。当创建一个新对象时,prototype方法自动被使用。

util.inherits(constructor,superconstructor)原形constructor被设定为原形superConstructor,并在一个新的对象被创建时执行。可以通过使用constructor.super_属性从自定义对象的构造函数访问supercontructor.

二、Readable流

有的前传util模块从其他对象继承的功能的了解,Readable就很好理解了.主要它包含以下方法和事件。

1.事件:

readable:在数据块可以从流中读取的时候发出。

data:类似readable,不同之处在于,当数据的事件处理程序被连接时,流被转变成流动的模式,并且数据处理程序被连续的调用,直到所有数据都被用尽

end:当数据不再被提供时由流发出

close:当底层资源,如文件,已关闭时发出。

error:在接收数据中出错是发出。

2.方法:

read([size]):从流中读数据.数据可以是String、Buffer、null(下面代码会有),当指定size,那么只读仅限于那个字节数

setEncoding(encoding):设置read()请求读取返回String时使用的编码

pause():暂停从该对象发出的data事件

resume():恢复从该对象发出的data事件

pipe(destination,[options]):把这个流的输出传输到一个由deatination(目的地)指定的Writable流对象。options是一个js对象.例如:{end:true}当Readable结束时就结束Writable目的地。

unpipe([destination]):从Writale目的地断开这一对象。

3.demo:

var stream = require('stream');
var util = require('util');
util.inherits(Answers, stream.Readable);
function Answers(opt) {
  stream.Readable.call(this, opt);
  this.quotes = ["yes", "no", "maybe"];
  this._index = 0;
}
Answers.prototype._read = function() {
  if (this._index > this.quotes.length){
    this.push(null);
  } else {
    this.push(this.quotes[this._index]);
    this._index += 1;
  }
};
var r = new Answers();
console.log("Direct read: " + r.read().toString());
r.on('data', function(data){
  console.log("Callback read: " + data.toString());
});
r.on('end', function(data){
  console.log("No more answers.");
});
r.on('readable',function(data)
{
   console.log('readable');
});

"C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" F:\nodejs\node.exe stream_read.js
Direct read: yes
readable
Callback read: no
Callback read: maybe
readable
readable
readable
No more answers.

Process finished with exit code 0

上面定义了一个通过util.inherits()继承Readable流的对象,从输出结果可以看到输出了3个字符串,但readable事件确执行了4次,其实前面也有写,read()可以是null,最后是push(null)了。

三、Writable流

有读就会有写,毕竟是可逆的,它和readable一样也有一些事件和方法

1.方法

write(chunk,[encoding],[callback]):将数据写入流。chunk(数据块)中包含要写入的数据,encoding指定字符串的编码,callback指定当数据已经完全刷新时执行的一个回调函数。如果成功写入,write()返回true.

end([chunk],[encoding],[callback]):与write()相同,它把Writable对象设为不再接受数据的状态,并发送finish事件。

2.事件

drain:在write()调用返回false后,当准备好开始写更多数据时,发出此事件通知监视器。

finish:当end()在Writable对象上调用,所以数据被刷新,并不会有更多的数据被接受时触发

pipe:当pipe()方法在Readable流上调用,已添加此writable为目的地时发出

unpipe:当unpipe()方法被调用,以删除Writable为目的地时发出。

3.demo

var stream = require('stream');
var util = require('util');
util.inherits(Writer, stream.Writable);
function Writer(opt) {
  stream.Writable.call(this, opt);
  this.data = new Array();
}
Writer.prototype._write = function(data, encoding, callback) {
  this.data.push(data.toString('utf8'));
  console.log("Adding: " + data);
  callback();
};
var w = new Writer();
for (var i=1; i<=5; i++){
  w.write("Item" + i, 'utf8');
}
w.end("ItemLast");
console.log(w.data);

"C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" F:\nodejs\node.exe stream_write.js
Adding: Item1
Adding: Item2
Adding: Item3
Adding: Item4
Adding: Item5
Adding: ItemLast
[ 'Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'ItemLast' ]

Process finished with exit code 0

四、把Readable流用管道输送到Writable流

上面也介绍了Readable流pipe()方法,这个主要是来测试

var stream = require('stream');
var util = require('util');
util.inherits(Reader, stream.Readable);
util.inherits(Writer, stream.Writable);
function Reader(opt) {
  stream.Readable.call(this, opt);
  this._index = 1;
}
Reader.prototype._read = function(size) {
  var i = this._index++;
  if (i > 10){
    this.push(null);
  } else {
    this.push("Item " + i.toString());
  }
};
function Writer(opt) {
  stream.Writable.call(this, opt);
  this._index = 1;
}
Writer.prototype._write = function(data, encoding, callback) {
  console.log(data.toString());
  callback();
};

var r = new Reader();
var w = new Writer();
w.on('pipe',function(){
  console.log('pipe');
});
r.pipe(w);

"C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" F:\nodejs\node.exe stream_piped.js
pipe
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9
Item 10

Process finished with exit code 0
时间: 2024-11-30 06:41:29

Node.js数据流Stream之Readable流和Writable流的相关文章

Node.js数据流Stream之Duplex流和Transform流

Duplex流一个很好的例子是TCP套接字连接.需要实现_read(size)和_Write(data,encoding,callback)方法. var stream = require('stream'); var util = require('util'); util.inherits(Duplexer, stream.Duplex); function Duplexer(opt) { stream.Duplex.call(this, opt); this.data = []; } Du

浅析Node.js的Stream模块中的Readable对象_node.js

我一直都很不愿意扯 nodejs 的流,因为从第一次看到它我就觉得它的设计实在是太恶心了.但是没办法,Stream 规范尚未普及,而且确实有很多东西都依赖了 nodejs 的流来实现的,所以我也只能捏着鼻子硬着头皮来扯一扯这又臭又硬的 nodejs 流对象了. nodejs 自带了一个叫 stream 的模块,引入它便可以得到一组流对象构造器.现在我只说最简单的 stream.Readable. 其实用过 nodejs 的几乎都接触过 Readable 的实例,只是平时没太在意而已.一个非常典型

浅析Node.js 中 Stream API 的使用_node.js

本文由浅入深给大家介绍node.js stream api,具体详情请看下文吧. 基本介绍 在 Node.js 中,读取文件的方式有两种,一种是用 fs.readFile ,另外一种是利用 fs.createReadStream 来读取. fs.readFile 对于每个 Node.js 使用者来说最熟悉不过了,简单易懂,很好上手.但它的缺点是会先将数据全部读入内存,一旦遇到大文件的时候,这种方式读取的效率就非常低下了. 而 fs.createReadStream 则是通过 Stream 来读取

node.js中 stream使用教程_node.js

这些日子跑去学了一下OC,但是还没有学成.离转行的时间还有很长,顺便回顾一下node的知识. 每种语言来来去去的人很多,但我就离不开node.我并不是使用它开发,只是使用js相对多一些,因此还是研究node比较好,stream在node的地位是很高的.闲时也来看看这个内容,在node的路上,我还是新手. 今天下载了nodeschool的课程看,其中有一个例子.(我修改了一点点) var concat = require('concat-stream'); var http = require('

Node.js中的缓冲与流模块详细介绍_node.js

缓冲(buffer)模块 js起初就是为浏览器而设计的,所以能很好的处理unicode编码的字符串,但不能很好的处理二进制数据.这是Node.js的一个问题,因为Node.js旨在网络上发送和接收经常是以二进制格式传输的数据.比如:  - 通过TCP连接发送和接收数据:  - 从图像或者压缩文件读取二进制数据:  - 从文件系统读写数据:  - 处理来自网络的二进制数据流 而Buffer模块为Node.js带来了一种存储原始数据的方法,于是可以再js的上下文中使用二进制数据.每当需要在Node.

Node.js Streams文件读写操作详解_node.js

Node.js 天生异步和事件驱动,非常适合处理 I/O 相关的任务.如果你在处理应用中 I/O 相关的操作,你可以利用 Node.js 中的流(stream).因此,我们先具体看看流,理解一下它们是怎么简化 I/O 操作的吧.  流是什么流是 unix 管道,让你可以很容易地从数据源读取数据,然后流向另一个目的地. 简单来说,流不是什么特别的东西,它只是一个实现了一些方法的 EventEmitter .根据它实现的方法,流可以变成可读流(Readable),可写流(Writable),或者双向

Node.js中的流(Stream)介绍

 这篇文章主要介绍了Node.js中的流(Stream)介绍,本文讲解了什么是流.pipe方法.流的分类.Readable流状态的切换等内容,需要的朋友可以参考下     什么是流? 说到流,就涉及到一个*nix的概念:管道--在*nix中,流在Shell中被实现为可以通过 |(管道符) 进行桥接的数据,一个进程的输出(stdout)可被直接作为下一个进程的输入(stdin). 在Node中,流(Stream)的概念与之类似,代表一种数据流可供桥接的能力. pipe 流化的精髓在于 .pipe(

Node.js中的流(Stream)介绍_node.js

什么是流? 说到流,就涉及到一个*nix的概念:管道--在*nix中,流在Shell中被实现为可以通过 |(管道符) 进行桥接的数据,一个进程的输出(stdout)可被直接作为下一个进程的输入(stdin). 在Node中,流(Stream)的概念与之类似,代表一种数据流可供桥接的能力. pipe 流化的精髓在于 .pipe()方法.可供桥接的能力,在于数据流的两端(上游/下游 或称为 读/写流)以一个 .pipe()方法进行桥接. 伪代码的表现形式为: 复制代码 代码如下: //上游.pipe

Node.js Stream - 进阶篇

上篇(基础篇)主要介绍了Stream的基本概念和用法,本篇将深入剖析背后工作原理,重点是如何实现流式数据处理和 back pressure 机制. 目录 本篇介绍 stream 是如何实现流式数据处理的. 数据生产和消耗的媒介 为什么使用流取数据 下面是一个读取文件内容的例子: const fs = require('fs') fs.readFile(file, function (err, body) { console.log(body) console.log(body.toString(