深入浅出node读书笔记(四)

  本篇文章介绍Buffer相关的概念。前端JavaScript对字符串的操作相对友好,有一系列比较好用的api来操作字符串。但是如果把js挪到后端,这些api明显不够,因为node在处理的时候需要大量处理一些二进制文件,前端那些api是远远不足的,于是buffer对象应运而生。

  首先,buffer模块在node启动的时候已经自动加载进去了,无需require()进去。

  (1)buffer对象类似数组,它的元素是16进制的两位数,都在0~255之间。用.length属性能够得到buffer的长度。我们在把字符串转为buffer对象之后,是能够设置buffer[]里面的值的,如果设置范围不在0~255之间,node会自动+(-)256来规范数值,如果是小数则舍弃小数部分。

  (2)buffer的内存分配。

    该分配取决于buffer对象的大小,该大小以8kb来界定,小于8k的为小buffer,这也是操作系统的slab动态内存分配机制:slab是一块已经申请好的内存块,如果是小buffer对象,则会把对象分到一个slab中,如果slab没满,就继续放,如果slab剩下的空间不足以放一个buffer对象,则会启用下一个slab,之前的slab剩余被浪费掉。如果是一个超过8kb的大buffer对象,操作系统将会分配一个slowBuffer对象作为slab来被大buffer对象独立占据。

  (3)buffer转换:

    字符串转buffer

var str='我是谁';
var str2='abcde';
var buf=new Buffer(str,'utf-8');
//buffer对象可能是多次写入
buf.write(str2);

    buffer转字符串:转化过程中因为截取buffer原因会出现乱码。

buf.toString();

   (4)buffer的拼接:

var fs = require('fs');
var rs = fs.createReadStream('test.md');
var data = '';
rs.on("data", function (chunk){ 
    data += chunk; //此处隐藏data与chunk的toString()操作
});
rs.on("end", function () { 
    console.log(data);
});

     在外语中这样操作没问题,但如果是中文,每个汉字转化为三个buffer二进制值,就会因截取的任意性而在tostring的过程中转化为乱码,这也就是乱码产生的原因。

  (5)解决乱码的方法:此处只介绍一种较通用的方法:把一些小的buffer对象拼接成一个buffer对象,一次性转码。

    

var chunks = [];
var size = 0;
res.on('data', function (chunk) {
  chunks.push(chunk);
  size += chunk.length; 
});
res.on('end', function () {
  var buf = Buffer.concat(chunks, size); 
  var str = iconv.decode(buf, 'utf8');
  console.log(str);
});

 

  chunks数组每次把读取的buf对象chunk加入到数组中,然后记录下总length。然后通过Buffer.concat(chunks,size)来把小的buf对象拼接成一个大的,然后转码即不会出现乱码。

  (6)buffer与性能:静态内容转为为buffer对象形式在网络中传输速度较快,效率高。

    在文件读取的时候,我们会设置一些属性,其中有一个highWaterMark属性,该属性决定读取文件的速度,表示每次从文件中读出多少字节。

    fs.createReadStream()的工作􏲵􏵖方式是在内􏶒中􏵮􏵣一􏰛Buffer,􏳎后在fs.read()读􏰴取文件时候将字节复制􏷲到Buffer中。􏵉􏰡完成一次读取操作,􏷤从这个Buffer中􏲊通过slice()􏲵􏳃􏰴􏱫方法取出一部分数据􏷧作为一个小Buffer对􏱷像,通􏼆􏲊过data事件􏰐􏲻􏵰􏵲􏲨传递给调用方。如果Buffer用完,重新申请一个,没用完则接着用。  

      

 

posted @ 2016-01-10 22:41  阿鼻地狱  阅读(202)  评论(0编辑  收藏  举报