Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all articles
Browse latest Browse all 14821

Buffer的转码

$
0
0

一、Buffer和String的相互转化 * String——>Buffer:var buf = new Buffer( str,[encoding] ); 第二个参数是字符编码(选填)

                         -------:buf.write(str, [offset], [length], [encoding]);

* Buffer——>String:buf.toString( [encoding] );按照编码将Buffer转换成字符串,默认是"utf-8"

                         --------: buf.toString( [encoding], [offset], [end]);

二、Buffer拼接 buffer拼接时的问题: 01.txt:“窗前明月光,疑是地上霜;举头望明月,低头思故乡。”

var rs = fs.createReadStream(“01.txt”); var data = ‘’; rs.on(‘data’, function (chunk) { data += chunk; }); rs.on(‘end’, function () { console.log(data); });

data事件中,chunk是Buffer对象。在执行 data += chunk;时,其实是 data = data.toString() + chunk.toString()。在国外的操作系统中是没有问题的,但是对于宽字节的中文(占3个字节),存在很大问题。

如果限定每次读出的Buffer字段最长为11个字节,那么会查询乱码 var rs = fs.createReadStream(“01.txt”,{higeWaterMark:11});

输出结果:窗前明???光,疑???是地上???;举头???明月,???头思故乡。 乱码的原因: 限定了每个Buffer是11个字节,在实行toString方法进行转换时,默认使用utf-8。汉字是款字节的(每个汉字占3个字节),那么第一个Buffer只能存储3个汉字+2个字节,由于这2个字节无法构成一个宽字节,因此显示2个乱码。第二个Buffer中,234字节才能构成一个宽字节,因此第一个字节,显示的乱码。 在不给流设置编码格式时,流内部用Buffer对象将数据传递给使用者,因此会可能产生乱码。 rs.setEncoding(‘utf-8’); 在设置编码格式后,流内部不使用Buffer对象来传递数据,而是使用decoder对象来将数据传递给使用者。

var StringDecoder = require(‘string_decoder’).StringDecoder; var decoder = new StringDecoder(‘utf-8’);

var buf1 = new Buffer([0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55]); //11个字节 console.log(buf1.toString()); //转化成3个汉字, var buf2 = new Buffer([0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55]); //11个字节 console.log(buf1.toString()); //转化成4个汉字

在输出buf1时,11个字节,其中有9个字节转化成3个汉字,剩下的2个字节会留在decoder对象中。 剩下的2个字节会和buf2中的字节进行组合。 但是decoder只支持base64、utf-8、UCS-2/UTF-16LE这3中编码格式。因此不是能通用的解决所有乱码问题 下面给出通用的解决方案: var rs = fs.createReadStream(“01.txt”,{higeWaterMark:11}); var data = []; var size = 0; rs.on(‘data’, function (chunk) { data.push(chunk); size += chunk.length; }); rs.on(‘end’, function () { var buf = Buffer.concat(data,size); console.log(buf.toString()); });

Buffer.concat( Array of Buffer, size); 该方法能将多个小buffer合并成一个大buffer。

下面给出concat的实现源码(细腻、优雅): function concat(list,length){ //1.判断list是不是Array,如果不是Array,直接返回null if( !Array.isArray(list) ){ return null; } //2.如果list的长度为1(只有一个buffer),则直接返回这个buffer if(list.length == 1){ return list[0]; } //3.判断length是否符合规范,不规范则重新计算length var len = list.length; if( typeof != ‘number’ ){ length = 0; for (let i = 0; i < len; i++) { length += list[i].length; } } //4.转化成Buffer var buf = new Buffer(length); var pos = 0; for(let i=0; i<len; i++){ buf.copy(list[i],pos); pos += list[i].length; } return buf; }


Viewing all articles
Browse latest Browse all 14821

Trending Articles