首页 > 代码库 > Nodejs读写流

Nodejs读写流

Nodejs读写流

流的传输过程默认是以buffer的形式传输的,除非你给他设置其他编码形式,
例如下面代码第二部分中,我们设置了流以utf8的编码形式进行传输:

 1 var readable stream1 = ... 2 readable stream1.on(‘data‘, function(data) { 3 // data is a buffer; 4 console.log(‘got this data:‘, data); 5 }); 6 var readable stream2 = ... 7 readable stream2.setEncoding(‘utf8‘); 8 readable stream2.on(‘data‘, function(data) { 9 // data is a utf8-encoded string;10 console.log(‘got this data:‘, data);11 });

流的传输过程是可以停止的,用pause()方法便可以暂停流的传输过程,
同理,流的传输过程还有对应的恢复方法,即重新恢复传输过程,采用resume()方法。

stream.pause();
stream.resume();

如果我们希望在流传输完成后进行某些某些操作,我们可以监听他的end事件

1 var readable stream = ...2 readable stream.on(‘end‘, function() {3     console.log(‘the stream has ended‘);4 });

1.使用可写流(WRITABLE STREAMS)
所谓可写流,就是可以一个允许你写入数据的对象。
最简单的操作可写流的方式就是使用write方法:
var writable_stream = ...;
writable_stream.write(‘this is an UTF-8 string‘);
你传入一个字符串形式作为参数的话,默认就是utf8编码的,当然你也可以再第二个参数中传入你想要的编码形式:
var writable_stream = ...;
writable_stream.write(‘7e3e4acde5ad240a8ef5e731e644fbd1‘, ‘base64‘);
又或者,你也可以将buffer写入可写流中:
var writable_stream = ...;
var buffer = new Buffer(‘this is a buffer with some string‘);
writable_stream.write(buffer);
在这里需要注意的一点是,在写进流的过程中,node并不一定能够及时的将数据写入kernel buffer,这个时候Node就会
将数据保存在缓冲队列中,在适当的时候才会重新将数据写入到正确的位置,这个时候可能需要监听一些事件来知道
何时那些缓冲队列的数据被重新写入了,该事件就是drain.

1 var writable stream = ...;2 writable stream.on(‘drain‘, function() {3     console.log(‘drain emitted‘);4 });

2.创建文件系统流

var fs = require(‘fs‘);
var rs = fs.createReadStream(‘/path/to/file‘);
上面的代码创建了一个可读流,我们可以再传入第二个参数,第二个参数为一个json对象形式的参数,具有以下几个配置项:

1 {2     encoding:‘xx‘,3     fd:‘xx‘, //文件描述4     bufferSize:‘xx‘,5     start:‘xx‘,6     end:‘xx‘7 }

如果你已经打开了一个文件,你可以读的到他的文件描述,则可以在第二个参数中传入这个文件描述:

1 ar fs = require(‘fs‘);2 var path = ‘/path/to/my/file‘;3 fs.open(path, ‘r‘, function(err, fd) {4     fs.createReadStream(null, {fd: fd, encoding: ‘utf8‘});5     fs.on(‘data‘, console.log);6 });

3.创建文件可写流

var fs = require(‘fs‘);
var rs = fs.createWriteStream(‘/path/to/file‘, options);
第二个参数默认值如下:

1 { flags: ‘w‘,2 encoding: null,3 mode: 0666 }

你可以创建一个可以接受utf8编码的文件可写流:
var fs = require(‘fs‘);
var rs = fs.createWriteStream(‘/path/to/file‘, { encoding: ‘utf8‘ });

4.理解网络流
一个TCP连接既是可读流,又是可写流;而Http连接则不同,一个http request对象是可读流,而http response对象则是可写流。
5.理解客户端缓慢的问题
首先,服务器读取文件的速度是很快的,然而客户端写入的速度确不能跟服务器读取的速度一致,这就对导致服务器
读取数据的时候无法及时传送到客户端,就会采取缓存策略。这会带来一个严重的问题,服务器内存爆满。
为了解决这个问题,我们需要监听客户端写入的事件是否正常,如果可以正常写入则服务器端则继续读取数据并传送。
在上面提到了流的传输过程是可以中断和继续的,并且有drain事件可以监听的到,我们可以利用这些特性来优化我们的
读写流的过程。一般情况下,如果我们不处理这种问题的话,代码像下面这样是很容易出现问题的:

1 require(‘http‘).createServer(function(req, res) {2     var rs = fs.createReadStream(‘/path/to/big/file‘);3     rs.on(‘data‘, function(data) {4         res.write(data);5     });6     rs.on(‘end‘, function() {7         res.end();8     });9 }).listen(8080);

代码中没有进行任何中断和持续的处理,如果写入流的过程能够正常的话,write()方法能够返回true,否则会返回false;
我们可以通过这样的API来优化我们的代码:

 1 require(‘http‘).createServer( function(req, res) { 2     var rs = fs.createReadStream(‘/path/to/big/file‘); 3     rs.on(‘data‘, function(data) { 4         if (!res.write(data)) { 5             rs.pause(); 6         } 7     }); 8     res.on(‘drain‘, function() { 9         rs.resume();10     });11     rs.on(‘end‘, function() {12         res.end();13     });14 }).listen(8080);

上面的过程在读写流的时候是很常见的,因此Node给出了一个通用的方法,就是pipe();该方法解决了上述所提到的这些问题。

1 require(‘http‘).createServer(function(req, res) {2     var rs = fs.createReadStream(‘/path/to/big/file‘);3     rs.pipe(res);4 }).listen(8080);

默认情况下,数据传送完成后就会调用end()方法,如果你希望调用自定义的end的话,则可以添加一个参数给他:

1 require(‘http‘).createServer(function(req, res) {2     var rs = fs.createReadStream(‘/path/to/big/file‘);3     rs.pipe(res, { end: false });4     rs.on(‘end‘, function() {5         res.write("And that‘s all, folks!");6         res.end();7     });8 }).listen(8080);