Node.js中的缓冲与流模块详细介绍


Posted in Javascript onFebruary 11, 2015

缓冲(buffer)模块

js起初就是为浏览器而设计的,所以能很好的处理unicode编码的字符串,但不能很好的处理二进制数据。这是Node.js的一个问题,因为Node.js旨在网络上发送和接收经常是以二进制格式传输的数据。比如:

 - 通过TCP连接发送和接收数据;
 - 从图像或者压缩文件读取二进制数据;
 - 从文件系统读写数据;
 - 处理来自网络的二进制数据流

而Buffer模块为Node.js带来了一种存储原始数据的方法,于是可以再js的上下文中使用二进制数据。每当需要在Node.js中处理I/O操作中移动的数据时,就有可能使用Buffer模块。

类:Buffer

Buffer 类是一个全局变量类型,用来直接处理2进制数据的。 它能够使用多种方式构建。

原始数据保存在 Buffer 类的实例中。一个 Buffer 实例类似于一个整数数组

1.new Buffer(size):分配一个新的 buffer 大小是 size 的8位字节.
2.new Buffer(array):分配一个新的 buffer 使用一个8位字节 array 数组.
3.new Buffer(str, [encoding]):encoding String类型 - 使用什么编码方式,参数可选.

4.类方法: Buffer.isEncoding(encoding):如果给定的编码 encoding 是有效的,返回 true,否则返回 false。
5.类方法: Buffer.isBuffer(obj):测试这个 obj 是否是一个 Buffer. 返回Boolean
6.类方法: Buffer.concat(list, [totalLength]):list {Array}数组类型,Buffer数组,用于被连接。totalLength {Number}类型 上述Buffer数组的所有Buffer的总大小。
除了可以读取文件得到Buffer的实例外,还能够直接构造,例如:

var bin = new Buffer([ 0x48, 0x65, 0x6c, 0x6c, 0x6c ]);

Buffer与字符串类似,除了可以用.length属性得到字节长度外,还可以用[index]方式读取指定位置的字节,例如:

bin[0]; // => 0x48;

Buffer与字符串能够互相转化,例如可以使用指定编码将二进制数据转化为字符串:
var str = bin.toString('utf-8'); // => "hello"

.slice方法不是返回一个新的Buffer,而更像是返回了指向原Buffer中间的某个位置的指针,如下所示。
1.[ 0x48, 0x65, 0x6c, 0x6c, 0x6c ]

2.    ^           ^

3.    |           |

4.   bin     bin.slice(2)

写入缓冲区

var buffer = new Buffer(8);//创建一个分配了8个字节内存的缓冲区

console.log(buffer.write('a','utf8'));//输出1

这会将字符"a"写入缓冲区,node返回经过编码以后写入缓冲区的字节数量,这里的字母a的utf-8编码占用1个字节。

复制缓冲区

Node.js提供了一个将Buffer对象整体内容复制到另一个Buffer对象中的方法。我们只能在已经存在的Buffer对象之间复制,所以必须创建它们。

buffer.copy(bufferToCopyTo)

其中,bufferToCopyTo是要复制的目标Buffer对象。如下示例:

var buffer1 = new Buffer(8);

buffer1.write('nice to meet u','utf8');

var buffer2 = new Buffer(8);

buffer1.copy(buffer2);

console.log(buffer2.toString());//nice to meet u

流模块

在UNIX类型的操作系统中,流是个标准的概念。有如下三个主要的流:

1.标准输入
2.标准输出
3.标准错误

可读流

如果说,缓冲区是Node.js处理原始数据的方式的话,那么流通常是Node.js移动数据的方式。Node.js中的流是可读的或者可写的。Node.js中许多模块都使用了流,包括HTTP和文件系统。

假设我们创建一个classmates.txt的文件,并从中读入姓名清单,以便使用这些数据。由于数据是流,这就意味着完成文件读取之前,从收到最初几个字节开始,就可以对数据动作,这是Node.js中的一个常见模式:

var fs = require('fs');

var stream = fs.ReadStream('classmates.txt');

stream.setEncoding('utf8');

stream.on('data', function (chunk) {

    console.log('read some data')

});

stream.on('close', function () {

    console.log('all the data is read')

});

在以上示例中,在收到新数据时触发事件数据。当文件读取完成后触发关闭事件。

可写流

显然,我们也可以创建可写流以便写数据。这意味着,只要一段简单的脚本,就可以使用流读入文件然后写入另一个文件:

var fs = require('fs');

var readableStream = fs.ReadStream('classmates.txt');

var writableStream = fs.writeStream('names.txt');

readableStream.setEncoding('utf8');

readableStream.on('data', function (chunk) {

    writableStream.write(chunk);

});

readableStream.on('close', function () {

    writableStream.end();

});

现在,当接收到数据事件时,数据会被写入可写流中。

readable.setEncoding(encoding):返回: this

readable.resume():同上。该方法让可读流继续触发 data 事件。

readable.pause():同上。该方法会使一个处于流动模式的流停止触发 data 事件,切换到非流动模式,并让后续可用数据留在内部缓冲区中。
类: stream.Writable

Writable(可写)流接口是对您正在写入数据至一个目标的抽象。

1.writable.write(chunk, [encoding], [callback]):

chunk {String | Buffer} 要写入的数据
encoding {String} 编码,假如 chunk 是一个字符串
callback {Function} 数据块写入后的回调
返回: {Boolean} 如果数据已被全部处理则 true。

该方法向底层系统写入数据,并在数据被处理完毕后调用所给的回调。

2.writable.cork():强行滞留所有写入。

滞留的数据会在 .uncork() 或 .end() 调用时被写入。

3.writable.end([chunk], [encoding], [callback])

chunk {String | Buffer} 可选,要写入的数据
encoding {String} 编码,假如 chunk 是一个字符串
callback {Function} 可选,流结束后的回调
在调用 end() 后调用 write() 会产生错误。

// 写入 'hello, ' 然后以 'world!' 结束

http.createServer(function (req, res) {

  res.write('hello, ');

  res.end('world!');

  // 现在不允许继续写入了

});
Javascript 相关文章推荐
javascript 常用关键字列表集合
Dec 04 Javascript
jQuery 使用手册(六)
Sep 23 Javascript
设置checkbox为只读(readOnly)的两种方式
Oct 11 Javascript
如何在父窗口中得知window.open()出的子窗口关闭事件
Oct 15 Javascript
基于socket.io和node.js搭建即时通信系统
Jul 30 Javascript
AngularJS入门知识之MVW类框架的编程思想探讨
Dec 08 Javascript
15款jQuery分布引导插件分享
Feb 04 Javascript
jQuery+ajax实现滚动到页面底部自动加载图文列表效果(类似图片懒加载)
Jun 07 Javascript
javaScript知识点总结(必看篇)
Jun 10 Javascript
全面理解JavaScript中的继承(必看)
Jun 16 Javascript
jQuery简单实现的HTML页面文本框模糊匹配查询功能完整示例
May 09 jQuery
JavaScript函数式编程(Functional Programming)组合函数(Composition)用法分析
May 22 Javascript
javascript中var的重要性分析
Feb 11 #Javascript
JavaScript设计模式之工厂模式和构造器模式
Feb 11 #Javascript
js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
Feb 11 #Javascript
45个JavaScript编程注意事项、技巧大全
Feb 11 #Javascript
JS实现判断碰撞的方法
Feb 11 #Javascript
javascript异步编程代码书写规范Promise学习笔记
Feb 11 #Javascript
jquery实现动态操作select选中
Feb 11 #Javascript
You might like
也谈截取首页新闻 - 范例
2006/10/09 PHP
php实现从上传文件创建缩略图的方法
2015/04/02 PHP
php正则表达式验证(邮件地址、Url地址、电话号码、邮政编码)
2016/03/14 PHP
[原创]php使用curl判断网页404(不存在)的方法
2016/06/23 PHP
基于Jquery的开发个代阴影的对话框效果代码
2011/07/28 Javascript
TextArea不支持maxlength的解决办法(jquery)
2011/09/13 Javascript
jQuery函数的等价原生函数代码示例
2013/05/27 Javascript
Jquery ajax执行顺序 返回自定义错误信息(实例讲解)
2013/11/06 Javascript
JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)
2013/11/25 Javascript
三种动态加载js的jquery实例代码另附去除js方法
2014/04/30 Javascript
JavaScript中数据结构与算法(五):经典KMP算法
2015/06/19 Javascript
JS在一定时间内跳转页面及各种刷新页面的实现方法
2016/05/26 Javascript
JS不完全国际化&本地化手册 之 理论篇
2016/09/27 Javascript
JavaScript的变量声明提升问题浅析(Hoisting)
2016/11/30 Javascript
js记录点击某个按钮的次数-刷新次数为初始状态的实例
2017/02/15 Javascript
AngularJS前端页面操作之用户修改密码功能示例
2017/03/27 Javascript
node.js平台下的mysql数据库配置及连接
2017/03/31 Javascript
Javascript中从学习bind到实现bind的过程
2018/01/05 Javascript
Vue 后台管理类项目兼容IE9+的方法示例
2019/02/20 Javascript
Vue实现base64编码图片间的切换功能
2019/12/04 Javascript
VUE实现自身整体组件销毁的示例代码
2020/01/13 Javascript
PyCharm在win10的64位系统安装实例
2017/11/26 Python
python开启debug模式的方法
2019/06/27 Python
Python 写了个新型冠状病毒疫情传播模拟程序
2020/02/14 Python
Python数据结构dict常用操作代码实例
2020/03/12 Python
浅谈keras中的后端backend及其相关函数(K.prod,K.cast)
2020/06/29 Python
CSS实现半透明边框与多重边框的场景分析
2019/11/13 HTML / CSS
详解canvas绘制网络字体几种方法
2019/08/27 HTML / CSS
应届生文秘专业个人自荐信格式
2013/09/21 职场文书
计算机维护专业推荐信
2014/02/27 职场文书
教师党员公开承诺书
2014/03/25 职场文书
2014年大学教师工作总结
2014/12/02 职场文书
给学校的建议书400字
2015/09/14 职场文书
详解Js模块化的作用原理和方案
2021/04/29 Javascript
了解Redis常见应用场景
2021/06/23 Redis
idea 在springboot中使用lombok插件的方法
2021/08/02 Java/Android