Node核心模块之Stream
来源:互联网 发布:英语6级网络课程 编辑:程序博客网 时间:2024/05/22 22:41
Node核心模块之Stream
Node.js V6.9.4
流(stream)在node中是一个用于处理流数据的抽象接口,node中很对对象都是基于流的,如HTTP服务器,process.stdout请求
流是可读、可写的,或者既可读有可写,并且所有流都是EventEmitter的实例
流主要用于实现一个copy
方法
* const stream = require(‘stream’) *
1.流的四种类型
- Readable: 可以读取数据的流
- Writable: 可以写数据的流
- Duplex: 既可以读数据的流,有可以写数据的流
- Transform: 可以在写入和读取数据时修改或转换数据的双工流
2.buffer
* 可读流和可写流都将数据存储在内部缓冲区buffer中,当调用stream.push(chunk)时,数据被缓冲在可读流中,如果用户没有调用stream.read()读取流,那么在缓冲区中的流将会被一直存储 *
* 如果读缓冲区区中的buffer达到指定大小,则再次读取的流将不会被缓存,stream.write()也一样,一旦达到阈值,将返回false *
* stream.pipe()方法很好的解决上面的阈值问题, pipe()的目的在于将数据的缓冲限制在可接受的水平,被称为管道*
3.一个Node.js官网例子
const http = require('http');const server = http.createServer( (req, res) => { // req is an http.IncomingMessage, which is a Readable Stream // res is an http.ServerResponse, which is a Writable Stream let body = ''; // Get the data as utf8 strings. // If an encoding is not set, Buffer objects will be received. req.setEncoding('utf8'); // Readable streams emit 'data' events once a listener is added req.on('data', (chunk) => { body += chunk; }); // the end event indicates that the entire body has been received req.on('end', () => { try { const data = JSON.parse(body); // write back something interesting to the user: res.write(typeof data); res.end(); } catch (er) { // uh oh! bad json! res.statusCode = 400; return res.end(`error: ${er.message}`); } });});server.listen(1337);// $ curl localhost:1337 -d '{}'// object// $ curl localhost:1337 -d '"foo"'// string// $ curl localhost:1337 -d 'not json'// error: Unexpected token o
* 上例中: 可写流(res)暴露方法(write()、end()),这两个方法被用于将数据写入流中,可读流使用EventEmitter来通知应用程序何时可以读取流中的数据 *
4.可写流
* 可写流实际上是一块地方,就是存放读取的数据的地方,或者可以说内存 *
// 新建可写流: 方法一const Writable = require('stream').Writable;class MyWritable extends Writable { constructor(options) { // Calls the stream.Writable() constructor super(options); }}// 新建可写流: 方法二const Writable = require('stream').Writable;const util = require('util');function MyWritable(options) { if (!(this instanceof MyWritable)) return new MyWritable(options); Writable.call(this, options);}util.inherits(MyWritable, Writable);// 新建可写流: 方法三const Writable = require('stream').Writable;const myWritable = new Writable({ write(chunk, encoding, callback) { // write方法为必须 // ... }, writev(chunks, callback) { // ... }});
常见的可写流
- HTTP requests, on the client
- HTTP response, on the server
- fs write streams
- zlib streams
- crypto streams
- TCP sockets
- child process stdin
process.stdout, process.stderr
5.可读流
* 可读流是读取数据源的抽象,即数据存放的地方,或者说内存 *
// 新建可读流:方法一const Readable = require('stream').Readable;class MyReadable extends Readable { constructor(options) { // Calls the stream.Readable(options) constructor super(options); }} // 新建可读流:方法二const Readable = require('stream').Readable;const util = require('util');function MyReadable(options) { if (!(this instanceof MyReadable)) return new MyReadable(options); Readable.call(this, options);}util.inherits(MyReadable, Readable); // 新建可读流:方法三const Readable = require('stream').Readable;const myReadable = new Readable({ read(size) { //异步方法 // ... } push(chunk[,encoding]) //将数据chunk放进可读流队列里面});
常见的可写流
- HTTP response, on the client
- HTTP request, on the server
- fs read streams
- zlib streams
- crypto streams
- TCP sockets
- child process stdout and stderr
- child process stdout and stderr
- process.stdin
6.流的应用
* 对于小文件,可以使用可读流讲数据存在内存中,然后用可写流讲数据读取 *
const fs = require('fs');var src = fs.readFileSync('/home/clx/old.sql');fs.writeFileSync('/home/clx/new.sql', src); // 在/home/clx目录下会出现一个new.sql文件
* 上面的例子中当old.sql不大时没有问题,但是当old.sql变成一部电影或者几个G的’动作片’,那程序就会崩溃,有两种方法解决:一种是利用可读流暂停,一种是利用pipe管道 *
7.管道
** readable.pipe()将Writable流附加到可读流,使其自动切换到写流模式,并将其所有数据推送到附加的Writable。管道将自动管理流数据,使得当可读流大于可写流时数据不被丢失,或者内存被过多的占用,
即管道是一边读一遍写 **
const fs = require('fs');const Readable = require('stream').stream;let readable = new Readable({ read(size) { //为可写流添加read方法,可读流必须有该方法 this.push('/home/clx/old.mp4'); }});const writable = fs.createWriteStream('/home/clx/new.mp4');// 管道读写,结束后在/home/clx/目录下生成new.mp4文件readable.pipe(writable, {end: false}); // => 管道读写完后触发读写流'end'事件readable.on('end', () => { // => 为读写流注册'end'事件 write.end('End');})
* Node.js很多方法都是基于流的,只是被封装好了,我们看不见,流是很多应用的基础,主要用来处理二进制文件 *
- Node核心模块之Stream
- Node核心模块之Events
- Node核心模块之Path
- Node核心模块之QueryString
- Node核心模块之Net
- Node核心模块之fs
- node核心模块之path
- Node核心模块之fs模块
- Node.js stream模块
- Node.JS核心模块之module分析
- node核心模块之读取文件
- node.js之基本流处理模块stream
- Node.js基本模块stream
- node.js核心模块
- Node.js核心模块
- Node.js核心模块
- Node核心模块
- 【Node核心模块HTTP】
- org.springframework.util.AntPathMatcher 工具类
- 微信小程序分享
- Android完美实现截屏
- CentOS7 安装MySQL
- python遍历文件目录
- Node核心模块之Stream
- hdu 1253 胜利大逃亡
- socket与http的区别
- 本人大多数文章发表在博客园,以及个人博客上
- IOC学习
- Chapter 4: 序列式容器之 list
- PAT BASIC LEVEL 1013. 数素数 (20)
- 编程题源码链接
- 用NDK做了一个AES加密的库