• 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);
  • 相关阅读:
    vs中nodejs代码 resharper 提示 ECMAScript2015 Feature. your Current language level is ECMAScript5的解决办法
    port: ${SERVER_PORT:9190} #首先取环境变量,如果环境变量中没有,就取 9190 这个固定值
    SpringbBoot之JPA批量更新
    Linq To Object多字段组合唯一校验
    LINQ获取两个List的交集
    Linq实现分组后取最大(小)值
    Maven:浅析依赖(dependency)关系中 scope 的含义
    Source roots (or source folders) Test source roots (or test source folders; shown as rootTest)Resource rootsTest resource roots
    Parameter 0 of method sqlSessionTemplate in org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration required a single bean, but 2 were found:
    sping boot/cloud配置文件 on 读取为true
  • 原文地址:https://www.cnblogs.com/moyiqing/p/node_stream.html
Copyright © 2020-2023  润新知