汴水流,泗水流,流到瓜州古渡头, 吴山点点愁。    我们知道水是源源不断的, 抽刀断水水更流, 斩不断, 理还乱,  是水流。(技术贴, 本文权当读者没学过古诗).

    在一些语言里, 我们的前辈把数据当成水流, 于是有了数据流的说法~  很贴切, 也很好理解。 今天呢, 我们就一起来看看node.js里面的stream数据流。

    stream是一个抽象的接口, node里有很多对象实现了这个接口, 如: 对http服务器发起请求的request对象就是一个Stream, 还有stdout(标准输出);

    node.js  Stream有四种流类型:

    1) Readable    可读操作

    2) Writable     可写操作

    3) Duplex       可读可写操作

    4) Transform   操作被写入数据, 然后读出结果(大致是说, 你把数据载入我的方法里, 我帮你处理后再返回给你)

    而且所有的stream 都是Events 对象的实例, 也就是说可以直接添加各种监听事件哈~ 常用的stream流的事件有:

    1) data    当有数据可读时候触发

    2) end     没有更多数据可读时触发

    3) erroe   在接收和写入过程中发生错误时触发

    4) finish   所有数据已被写入时触发 (写入操作时候用)

    

    好了, 那我们简单说下怎么从流重读取数据, 创建love.txt, 内容如下:        这不是一封情书: i love ~ ♥

    创建readStream.js 文件

var fs = require("fs");
var data = ''; // 定义data 接收数据 // 创建可读流
var readerStream = fs.createReadStream('love.txt'); // 设置编码为 utf8。
readerStream.setEncoding('UTF8'); // 其实默认就是utf8 去掉也无妨, 这里只是为了小伙伴们知道怎么去指定编码 // 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) { // chunk 是一种数据传输机制, 把数据流分成小块输出过来
data += chunk;
});
readerStream.on('end',function(){  // 必须数据传输完成后 才能打印出data
console.log(data);
}); readerStream.on('error', function(err){
console.log(err.stack);
}); console.log("程序执行完毕");

  运行结果如下

程序执行完毕
这不是一封情书: i love ~ ♥

  成功读取到文件内容,  那么怎么去写入内容呢

  

var fs = require("fs");
var data = '杨帅要写入的内容'; // 创建一个可以写入的流,写入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt'); // 使用 utf8 编码写入数据
writerStream.write(data,'UTF8'); // 写完后停止写入
writerStream.end(); // 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
console.log("写入完成");
}); writerStream.on('error', function(err){
console.log(err.stack); // 打印错误信息
}); console.log("程序执行完毕");

   跑一下

   然后查看目录里, 多了一个output.txt的文件, 文件内容为:

杨帅要写入的内容

   符合预期,   可是代码不够优雅,  也不够精简, 那么有更简单的方法么,   有!

   node里面提供了一个输出流到输入流的机制(pipe) , 俗称管道流。 有了这个小玩意儿,  可以事半功倍哦(而且还有一些防止读入过快, 写入过慢, 也就是俗称爆仓的功效)。麻雀虽小五脏俱全!

     ok,   有了它 , 画风是这样的

  

//  十分好用的管道流
var fs = require('fs');
var readFile = fs.createReadStream('love.txt'); var writeFile = fs.createWriteStream('copy-input.txt'); // 创建可写流 并写入copy-input.txt readFile.pipe(writeFile); console.log('数据传输完成');

    看起来很甜美的代码, 运行测试一下

    果然出现了一个copy-input.txt的文件M 内容为

    这不是一封情书: i love  ~ ♥  
  

链式流  

   我们知道, 管道不一定是直达的,  那么我们怎么达到我们的目标点呢。 当然是接水管呀~

    在node里,  我们可以通过链式的方法来对数据进行一些中间层的操作。

    此时我们实现一个文件的压缩和解压的demo 来体验一下, 代码里会有详细的注释。

var fs = require('fs');
var zlib = require('zlib'); //压缩和解压文件模块 // 比如我们要把love.txt 压缩成 yangshuai.zzzz
// 先读取love.txt
fs.createReadStream('love.txt')
.pipe(zlib.createGzip()) // zlib.createGzip()是压缩文件的方法 这是一个transform流, 我们前面说过transform可以操作被写入数据, 然后读出结果
.pipe(fs.createWriteStream('yangshuai.zzzz')); console.log('看起来很严谨, 很nice');

运行一下

然后看目录

    

    果不其然, 这个压缩文件已经创建成功~  可是打开都是二进制编码 宝宝看不懂怎么办~

    没关系, 我们来解压一下

  

var fs = require('fs');
var zlib = require('zlib'); //压缩和解压文件模块 // 比如我们要把 yangshuai.zzzz 解压成 yangshuai.txt(为了区分, 不用love.txt)
// 先读取yangshuai.zzzoz
fs.createReadStream('yangshuai.zzzz')
.pipe(zlib.createGunzip()) // zlib.createGzip()是压缩文件的方法 这是一个transform流
.pipe(fs.createWriteStream('yangshuai.txt')); console.log('这段解压代码看起来也很严谨, 也很nice');

   

    是不是操作起来很方便呢~

    ok, stream 数据流我们就说到这里。小伙伴们有没有明了呢~

欢迎指正~  期待一起进步  2017, 加油

    

    愿得一人心 白首不相离

  

  

浅谈stream数据流的更多相关文章

  1. 浅谈React数据流管理

    引言:为什么数据流管理如此重要?react的核心思想就是:UI=render(data),data就是我们说的数据流,render是react提供的纯函数,所以用户界面的展示完全取决于数据层.这篇文章 ...

  2. 浅谈iOS视频开发

     浅谈iOS视频开发 这段时间对视频开发进行了一些了解,在这里和大家分享一下我自己觉得学习步骤和资料,希望对那些对视频感兴趣的朋友有些帮助. 一.iOS系统自带播放器 要了解iOS视频开发,首先我们从 ...

  3. 浅谈 Requests包

    浅谈 Requests包 一:Requests包是做什么的? 简单地说,是用python处理HTTP的一个包. 它的标志也非常有气质,是一个双蛇杖,按照官方的说法,一条蛇代表client,一条代表se ...

  4. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  5. .NET(C#):浅谈程序集清单资源和RESX资源

    原文:.NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

  6. 浅谈Vue不同场景下组件间的数据交流

    浅谈Vue不同场景下组件间的数据“交流”   Vue的官方文档可以说是很详细了.在我看来,它和react等其他框架文档一样,讲述的方式的更多的是“方法论”,而不是“场景论”,这也就导致了:我们在阅读完 ...

  7. 【ASP.NET MVC系列】浅谈ASP.NET MVC八大类扩展(上篇)

    lASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操 ...

  8. 浅谈一下mshta在CVE-2017-11882里的命令构造

    Evi1cg同学前不久放出CVE-2017-11882的一个 python利用脚本,地址在https://github.com/Ridter/CVE-2017-11882/,不过其中一个版本里边有一个 ...

  9. 浅谈 DDoS 攻击与防御

    浅谈 DDoS 攻击与防御 原创: iMike 运维之美  什么是 DDoS DDoS 是英文 Distributed Denial of Service 的缩写,中文译作分布式拒绝服务.那什么又是拒 ...

随机推荐

  1. SQL Server--导入和导出向导

    作用:创建一个只需要最少的转换就可以快速导入或导出数据的包 操作步骤: 1 打开打入和导出向导方式 有四种方式 1)在SSMS(SQL Server Management Studio)中,右击目标数 ...

  2. iOS开发——NSArray中的字典排序

    手头上碰到一个项目,需要给数组中的字典中的一个字段排序,想了想,干脆再字典中增加一个字段,用来记录需要排序字段的第一个字符,用它来作为比较的对象,进行排序. - (void)viewDidLoad { ...

  3. css01

      1.  常用属性:①color:文本颜色:②background-color:背景颜色:③font-size:文字大小: 2.  样式声明:①内部样式:style=“样式规则:”,写于作用标签内, ...

  4. css padding和margin的百分比

    前段时间我同事对于margin和padding应用百分比值似乎有些误解,觉得可能是个普遍问题,所以觉得有必要拿出来单独写一下. margin和padding都可以使用百分比值的,但有一点可能和通常的想 ...

  5. github上forck一个分支之后,如何和主分支同步

    github forck一个分之后,如果过一段时间就会和主分支的差异比较大. 这样提交pr的时候 就会冲突,这个时候我们就需要和主分支同步代码 git remote add upstream git@ ...

  6. vs生成解决方案错误无法将文件“xx.*”复制到xx.*”。对路径“bin\xx.*”的访问被拒绝

    使用vs2008生成解决方案时出现的问题: 无法将文件“obj\xx.*”复制到“bin\xx.*”.对路径“bin\xx.*”的访问被拒绝 解决方法: 将*.dll的只读属性去掉(在windows对 ...

  7. iOS开发——An App ID with identifier "*****" is not avaliable

    Error: An App ID with identifier "*****" is not avaliable. Please enter a different string ...

  8. iOS 消息推送原理及实现总结

    在实现消息推送之前先提及几个于推送相关概念,如下图:1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务 ...

  9. C++中string类的使用方法

    如果所比较的两个string 相等,则返回0: 操作string 大于参数string,返回 正数:操作string 小于参数string,返回负数. (1) 比较操作string 与 _Str 或C ...

  10. Memcached源码分析之请求处理(状态机)

    作者:Calix 一)上文 在上一篇线程模型的分析中,我们知道,worker线程和主线程都调用了同一个函数,conn_new进行事件监听,并返回conn结构体对象.最终有事件到达时,调用同一个函数ev ...