Nodejs读写流
2014-08-17 21:11 king0222 阅读(2722) 评论(0) 编辑 收藏 举报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);