文章目录
  1. 1. buffer的8KB
  2. 2. 何时使用buffer
  3. 3. buffer和string
  4. 4. 参考

对于JavaScript来说,对Unicode编码的数据很容易处理的但是对于二进制数据就没什么处理方法了。但是在一些TCP数据流或者在操作一些文件数据流的时候,字节流的处理方法还是必须的。nodeJS中便出了处理的策略方法~提供了与String类似对等的全局构造函数Buffer,Buffer是node中储存二进制数据的中介者。

buffer的8KB

buffer著名的8KB载体,举个例子好比,node把一幢大房子分成很多小房间,每个房间能容纳8个人,为了保证房间的充分使用,只有当一个房间塞满8个人后才会去开新的房间,但是当一次性有多个人来入住,node会保证要把这些人放到一个房间中,比如当前房间A有4个人住,但是一下子来了5个人,所以node不得不新开一间房间B,把这5个人安顿下来,此时又来了4个人,发现5个人的B房间也容纳不下了,只能再开一间房间C了,这样所有人都安顿下来了。但是之前的两间房A和B都各自浪费了4个和3个位置,而房间C就成为了当前的房间。

具体点说就是当我们实例化一个新的Buffer类,会根据实例化时的大小去申请内存空间,如果需要的空间小于8KB,则会多一次判定,判定当前的8KB载体剩余容量是否够新的buffer实例,如果够用,则将新的buffer实例保存在当前的8KB载体中,并且更新剩余的空间。

何时使用buffer

Node中许多地方的数据流均是使用的Buffer类型,以便于来处理一些二进制数据(比如读取文件数据,http请求中的post传递的数据等)。

var fs = require('fs');
var rs = fs.createReadStream('web.txt');
var data = '';
rs.on("data", function (trunk){
    data += trunk;
});
rs.on("end", function () {
    console.log(data);
});

这样是可以正常读取的,但是如果修改为

var rs = fs.createReadStream('web.txt',, { highWaterMark: 5 });

则中文不再可以正常读取,会出现乱码现象。

一个中文字占了3个Buffer单位,但是在数据流分块的时候将一个中文的3个标识分开,再做 toString的时候救会发生出现这种乱码的情况。。我们提到data += trunk等价于data = data.toString() + trunk.toString()。

解决方式就是在拿到的分块数据千万不能直接进行类似toString式转义,将每段Buffer保存,最后合并成一个大的Buffer后在进行转义:

var fs = require('fs');
var rs = fs.createReadStream('web.txt',  { highWaterMark: 5 });
var dataArr = [], len = 0;
var data = '';
rs.on("data", function (trunk){
    dataArr.push(chunk);
    len += chunk.length;
});
rs.on("end", function () {
    data = Buffer.concat( dataArr, len ).toString();
    console.log(data);
});

另一方面,我们还可以比较一下上面两种buffer拼接结束的性能:

var buf = new Buffer('nodejsv0.10.4&nodejsv0.10.4&nodejsv0.10.4&nodejsv0.10.4&');
console.time('string += buf')
var s = '';
for(var i=0;i<10000;i++){
    s += buf;
}
s;
console.timeEnd('string += buf')


console.time('buf concat')
var list = [];
var len=0;
for(var i=0;i<10000;i++){
    list.push(buf);
    len += buf.length;
}
var s2 = Buffer.concat(list, len).toString();
console.timeEnd('buf concat')

结果(某一次):

string += buf: 8ms
buf concat: 4ms

虽然每次结果都不相同,但是在1000次拼接过程中,两者的性能几乎相差一倍,而且当客户上传的是非UTF8的字符串时,直接+=还容易出现错误。

buffer和string

测试一下buffer和string拼接性能。

var buf = new Buffer('this is text concat test'),
 str = 'this is text concat test';
console.time('buffer concat test');
var list = [];
var len= 100000 * buf.length;
for(var i=0;i<10000000;i++){
    list.push(buf);
    len += buf.length;
}
var s1 = Buffer.concat(list, len).toString();
console.timeEnd('buffer concat test');

console.time('string concat test');
var list = [];
for (var i = 10000000; i >= 0; i--) {
  list.push(str);
}
var s2 = list.join('');
console.timeEnd('string concat test');

大致结果是

读取速度更不需要测试了,肯定string更快,buffer还需要toString()的操作。

所以我们在保存字符串的时候,该用string还是要用string,就算大字符串拼接string的速度也不会比buffer慢。

当我们保存非utf-8字符串,2进制等等其他格式的时候,我们就必须得使用buffer了。

参考

  1. 浅析nodejs的buffer类
  2. node的 Buffer 介绍
文章目录
  1. 1. buffer的8KB
  2. 2. 何时使用buffer
  3. 3. buffer和string
  4. 4. 参考