Node.js Stream读写数据流

 2015年05月29日    1175     声明


流(Stream)是一个抽象的数据接口,Node.js中很多对象都实现了流,流是EventEmitter对象的一个实例。在类UNIX系统Stream是通过"|"实现对流的操作,node.js中对流的操作是通过.pipe()方法。按流的可操作性有可读流和可写流之分。Stream 是一个可以重复使用的统一的接口,通过抽象的Stream接口可以实现控制对象之间Stream的读写平衡。

  1. 可读流操作
  2. 可写流操作
  3. 流的使用示例
  4. Buffer、fs、Stream之间的关系


1.可读流操作

在创建或者获取一个可读流(如:读取一个文件后、收到一个client端HTTPt responses后)之后,可以对其进行一些控制和操作。例如:可以通过暂停和恢复来控制数据的流动、可以在收到数据时得到data通知、可以在流终止时关闭传输。

1.1 'data' 事件等待数据传输

流会以块为单位发送二进制数据,通过监听"data"事件,可以在数据传输时通知及本次的数据块。示例如下:

var readable = getReadableStreamSomehow();   //getReadableStreamSomehow()是一个获得可读流的方法

readable.on('data', function(chunk) {
  //本次得到的数据块chunk
  console.log('got %d bytes of data', chunk.length);
});

1.2 流的暂停与恢复

可读流就像一个阀门,可以通暂停来数据流动,可以通resume()方法恢复传输。示例如下:

var readable = getReadableStreamSomehow();
readable.on('data', function(chunk) {
  console.log('got %d bytes of data', chunk.length);
  readable.pause(); //暂停
  console.log('接下来的1秒数据传输将会暂停');
  setTimeout(function() {
    console.log('数据传输恢复');
    readable.resume();   //恢复
  }, 1000);
});

1.3 流传输结束

流传输结果后会收到"end"事件,通过监听"end"事件可以进行一些流传输结束后的处理。示例如下:

var readable = getReadableStreamSomehow();   //getReadableStreamSomehow()是一个获得可读流的方法

readable.on('data', function(chunk) {
  //本次得到的数据块chunk
  console.log('got %d bytes of data', chunk.length);
});

readable.on('end', function() {
  console.log('数据传输结束');
});

1.4 Node.js中的可读流有


2.可写流操作

可写流可能会是一个文件,也可能是一个TCP或HTTP的网络连接等。通过对可写流的操作,可以实现向传输对象写入一些数据等。

2.1 将数据写入可写流

向流写入数据时,可以传送缓冲区Buffer数据或字符串。写入时,可设置第二个可选参数设置数据编码。示例如下:

var file = fs.createWriteStream('example.txt');
file.write('itbilu.com');
//写入数据时,可以设置编码格式
file.write('aXRiaWx1LmNvbQ==', 'base64');
//写缓冲区Buffer数据
var buf = new Buffer('itbilu.com');
file.write(buf);

2.2 可写流的完成与清空

向流写入数据时,你会知道缓冲区数据是否被立即刷新,如果没有被刷新数据会被存储到内存中。在流成功刷新挂起的缓冲区时,stream会发送“drain”事件。写入完成后会发送“finish”事件。示例如下:

var writer = fs.createWriteStream('example.txt');
//假设这是一个可能会被挂起的缓冲区
var buf = new Buffer('itbilu.com');
writer.write(buf);

//刷新挂起的缓冲区时可写流缓冲区被清空,发送drain事件
writer.on('drain', fuction(){
   //对挂起事件的处理
})

//写入完成或调用end()方法后,将会发送finish事件
writer.on('finish', function() {
  console.error('所有数据已经写入完成.');
});

2.3 Node.js中的可写流有


3.流的使用示例

创建一个http服务器,每当有请求进入时,从文件中读取一个可读流,将流转接到Http response可写流中。

var http=require('http');
var fs =require('fs');

//创建http服务
var server=http.createServer();

//监听request事伯
server.on('request',function (req, res) {
    //每当有请求进入时,fs会从demo.mp3文件创建一个可读流,并将数据pipe()接入到res响应流中
    res.writeHead(200,{'Content-Type':'audio/mp3'});
    var rs=fs.createReadStream('/home/liuht/demo.mp3');
    rs.pipe(res);
})
//启动服务
server.listen(3333);


4.Buffer、fs、Stream之间的关系

Buffer是数据缓冲区对象,是二制数据在内存中的表现形式。Buffer中的数据可以按stream的形式传递到其它对象中。
fs是文件操作对象,文件是数据在硬盘上的表现形式。fs读出数据后会放入Buffer中才能对数据进行操作。写入数据前,数据也应该放到Buffer对象中再写入到文件中。fs读写文件时,数据是按流(stream)形式进行传输的。
stream是数据传输对象,如果需要在传输过程中对数据进行处理,则需要处理流数据。如果把文件比做装数据的容器,那流是容器间数据传输的一个过程,流传输的对象就是Buffer(二进制)数据。