node总结之Stream(流)了解下

淩亂°似流年 2022-05-13 16:30 323阅读 0赞

简单来说 Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出)。在Node中有四种流类型:

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作.
  • Transform - 操作被写入数据,然后读出结果。

基本上所有的 Stream 对象都是 EventEmitter 的实例,常用的事件如下:

  • data - 当有数据可读时触发。
  • end - 没有更多的数据可读时触发。
  • error - 在接收和写入过程中发生错误时触发。
  • finish - 所有数据已被写入到底层系统时触发。

我们先来创建 input.txt 文件,做测试用,如下:

  1. luyaran is my lover

完事创建 main.js 文件, 代码如下:

  1. var fs = require("fs");
  2. var data = '';
  3. // 创建可读流
  4. var readerStream = fs.createReadStream('input.txt');
  5. // 设置编码为 utf8。
  6. readerStream.setEncoding('UTF8');
  7. // 处理流事件 --> data, end, and error
  8. readerStream.on('data', function(chunk) {
  9. data += chunk;
  10. });
  11. readerStream.on('end',function(){
  12. console.log(data);
  13. });
  14. readerStream.on('error', function(err){
  15. console.log(err.stack);
  16. });
  17. console.log("程序执行完毕");

再来看如何写入:

  1. var fs = require("fs");
  2. var data = 'luyaran';
  3. // 创建一个可以写入的流,写入到文件 output.txt 中
  4. var writerStream = fs.createWriteStream('output.txt');
  5. // 使用 utf8 编码写入数据
  6. writerStream.write(data,'UTF8');
  7. // 标记文件末尾
  8. writerStream.end();
  9. // 处理流事件 --> data, end, and error
  10. writerStream.on('finish', function() {
  11. console.log("写入完成。");
  12. });
  13. writerStream.on('error', function(err){
  14. console.log(err.stack);
  15. });
  16. console.log("程序执行完毕");

管道提供了一个输出流到输入流的机制,通常我们用于从一个流中获取数据并将数据传递到另外一个流中,来看下流程图:

70

如上面的图片所示,我们把文件比作装水的桶,而水就是文件里的内容,我们用一根管子(pipe)连接两个桶使得水从一个桶流入另一个桶,这样就慢慢的实现了大文件的复制过程。

来看实例:

  1. var fs = require("fs");
  2. // 创建一个可读流
  3. var readerStream = fs.createReadStream('input.txt');
  4. // 创建一个可写流
  5. var writerStream = fs.createWriteStream('output.txt');
  6. // 管道读写操作
  7. // 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
  8. readerStream.pipe(writerStream);
  9. console.log("程序执行完毕");

链式是通过连接输出流到另外一个流并创建多个流操作链的机制,一般用于管道操作。

接下来我们就是用管道和链式来压缩和解压文件,代码如下:

  1. var fs = require("fs");
  2. var zlib = require('zlib');
  3. // 压缩 input.txt 文件为 input.txt.gz
  4. fs.createReadStream('input.txt')
  5. .pipe(zlib.createGzip())
  6. .pipe(fs.createWriteStream('input.txt.gz'));
  7. console.log("文件压缩完成。");

执行完以上操作后,我们可以看到当前目录下生成了 input.txt 的压缩文件 input.txt.gz。接下来,让我们来解压该文件,创建 decompress.js 文件,代码如下:

  1. var fs = require("fs");
  2. var zlib = require('zlib');
  3. // 解压 input.txt.gz 文件为 input.txt
  4. fs.createReadStream('input.txt.gz')
  5. .pipe(zlib.createGunzip())
  6. .pipe(fs.createWriteStream('input.txt'));
  7. console.log("文件解压完成。");

现在嘞,又有了这么一个需求,就是把input里面的内容写到outInput里面去,但是上面的方法都是把文档里面的内容重置了,需求只想添加,而且保留原内容怎么办呢,我们可以在可读流创建完毕的回调函数里面进行操作,如下:

  1. let fs = require('fs');
  2. let data = '';
  3. let data2 = '你的小青蛙是真的可爱';
  4. //1.读取流
  5. //创建可读流
  6. let readStream = fs.createReadStream("input.txt");
  7. //设置utf-8编码
  8. readStream.setEncoding('UTF8');
  9. //处理流事件
  10. readStream.on('data', chunk => data += chunk);
  11. readStream.on('end', () => writeS(data));
  12. readStream.on("error", err => console.log(err.strck));
  13. console.log("程序1执行完毕");
  14. //2.写入流
  15. //创建可写流
  16. let writeS = dataS =>{
  17. let writeStream = fs.createWriteStream("outInput.txt");
  18. //使用utf-8写入流
  19. writeStream.write(data2+dataS, "UTF8");
  20. //标记文件末尾
  21. writeStream.end();
  22. //处理事件流
  23. writeStream.on("finish", () => console.log("写入完成"));
  24. writeStream.on("error", err => console.log(err.stack));
  25. console.log("程序2执行完毕");
  26. }

我们还可以设置写入流的追加参数来解决:

  1. var fs = require('fs');
  2. var read = fs.createReadStream('../data/input.txt');
  3. //设置第二个参数append
  4. var write = fs.createWriteStream('../data/out.txt', { 'flags': 'a' });
  5. //管道流读写操作
  6. read.pipe(write);
  7. console.log('执行完毕');

再来就是中文乱码问题了,咱们可以全局安装 iconv-lite 这个模块:

  1. npm install -g iconv-lite

代码样式如下:

  1. var iconv = require('iconv-lite');
  2. var fs = require('fs');
  3. var fileStr = fs.readFileSync('D:\\test.csv', {encoding:'binary'});
  4. var buf = new Buffer(fileStr, 'binary');
  5. var str = iconv.decode(buf, 'GBK');
  6. console.log(str);

原理很简单,就是先统一用二进制编码方式读取,然后再用 GBK 解码。

好啦,本次记录就到这里了。

如果感觉不错的话,请多多点赞支持哦。。。

发表评论

表情:
评论列表 (有 0 条评论,323人围观)

还没有评论,来说两句吧...

相关阅读

    相关 node总结多进程了解

    Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能,其中,每个子进程总是带有三个流对象:

    相关 node总结Web 模块了解

    Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,Web服务器的基本功能就是提供Web信息浏览服务。它只需支持HTTP协议、HTML文档格式及URL,与客户