Node进阶 ---- Buffer

1. 什么是Buffer

  • 缓冲区Buffer是暂时存放输入输出数据的一段内存。
  • JS语言没有二进制数据类型,而在处理TCP和文件流的时候,必须要处理二进制数据。
  • NodeJS提供了一个Buffer对象来提供对二进制数据的操作
  • 是一个表示固定内存分配的全局对象,也就是说要放到缓存区中的字节数需要提前确定
  • Buffer好比由一个8位字节元素组成的数组,可以有效的在JavasScript中表示二进制数据

2. 什么是字节

  • 字节(Byte)是计算机存储时的一种计量单位,一个字节等于8位二进制数
  • 一个位就代表一个0或1,每8个位(bit)组成一个字节(Byte)
  • 字节是通过网络传输信息的单位
  • 一个字节最大值十进制数是255 2**8-1;

进制

  • 0b 2进制

  • 0x 16进制

  • 0o 8进制

  • 将任意进制字符串转换为十进制

    • parseInt("11", 2); // 3 2进制转10进制
    • parseInt("77", 8); // 63 8进制转10进制
    • parseInt("e7", 16); //175 16进制转10进制
  • 将10进制转换为其它进制字符串

    • (3).toString(2)) // "11" 十进制转2进制
    • (17).toString(16) // "11" 十进制转16进制
    • (33).toString(32) // "11" 十提制转32进制

3. 定义buffer的三种方式

3.1 通过长度定义buffer

// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 创建一个长度为 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为 10、且未初始化的 Buffer。
const buf3 = Buffer.allocUnsafe(10);

3.2 通过数组定义buffer

// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);

正常情况下为0-255之间;

3.3 字符串创建

const buf5 = Buffer.from('张熙沐枫');

4.buffer常用方法

4.1 buf.fill(value[, offset[, end]][, encoding])

手动初始化,擦干净桌子,将buffer内容清0

buffer.fill(0);

4.2 write方法

buf.write(string[, offset[, length]][, encoding])

buffer.write('沐',0,3,'utf8');
buffer.write('枫',3,3,'utf8'); //沐枫

4.3 writeInt8

var buf = new Buffer(4);
buf.writeInt8(0,0);
buf.writeInt8(16,1);
buf.writeInt8(32,2);
buf.writeInt8(48,3);//16*3*/
console.log(buf);
console.log(buf.readInt8(0));
console.log(buf.readInt8(1));
console.log(buf.readInt8(2));
console.log(buf.readInt8(3));

4.3.1 Little-Endian&Big-Endian

不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序。

  • Big-endian:将高序字节存储在起始地址(高位编址)

  • Little-endian:将低序字节存储在起始地址(低位编址)

    let buf3 = new Buffer(4);
    buf3.writeInt16BE(2**8,0);
    console.log(buf3);//<Buffer 01 00 00 00>
    console.log(buf3.readInt16BE(0));
    
    buf3.writeInt16LE(2**8,2);
    console.log(buf3);//<Buffer 01 00 00 01>
    console.log(buf3.readInt16LE(2));
    

4.3 toString方法

buf.toString([encoding[, start[, end]]])

buffer.toString('utf8',3,6)

4.4 slice方法 [#](#t134.4 slice方法)

buf.slice([start[, end]])

let newBuf = buffer.slice(0,4);

4.4.1 截取乱码问题

let {StringDecoder}  = require('string_decoder');
let sd = new StringDecoder();
let buffer = new Buffer('沐枫');
console.log(sd.write(buffer.slice(0,4)));
console.log(sd.write(buffer.slice(4)));

4.5 copy方法

复制Buffer 把多个buffer拷贝到一个大buffer上

buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
let buf5 = Buffer.from('张熙沐枫');
let buf6 = Buffer.alloc(6);
buf5.copy(buf6,0,0,4);
buf5.copy(buf6,3,3,6);
//buf6=沐枫
Buffer.prototype.copy2 = function(targetBuffer,targetStart,sourceStart,sourceEnd){
    for(let i=sourceStart;i<sourceEnd;i++){
        target[targetStart+i] = this[i];
    }
}

4.6 concat方法

Buffer.concat(list[, totalLength])
let buf1 = Buffer.from('沐');
let buf2 = Buffer.from('枫');
let buf3 = Buffer.concat([buf1,buf2],3);
console.log(buf3.toString());
Buffer.concat2 = function (list = [], total = list.reduce((len, item) => len + item.length, 0)) {
    if (list.length == 1)
        return list[0];
    let result = Buffer.alloc(total);
    let pos = 0;
    for (let bf of list) {
        for (let b of bf) {
            if (pos < total)
                result[pos++] = b;
            else
                return result;
        }
    }
    return result;
}
Buffer.myConcat = function(list,totalLength=list.reduce((len,item)=>len+item.length,0)){
  if(list.length==0)
    return list[0];
  let newBuffer = Buffer.alloc(totalLength);
  let offset = 0;
  for(let i=0;i<list.length;i++){
    if(offset+list[i].length>totalLength){
      list[i].copy(newBuffer,offset,0,totalLength-offset);
      break;
    }else{
      list[i].copy(newBuffer,offset,0,list[i].length);
      offset+=list[i].length;
    }
  }
  return newBuffer;
}

4.7 isBuffer

判断是否是buffer

Buffer.isBuffer

4.8 length

获取字节长度(显示是字符串所代表buffer的长度)

Buffer.byteLength("沐枫");
buffer.length;

6. base64

  • Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。

  • Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3_8 = 4_6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3

    const CHARTS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    function transfer(str){
      let buf = Buffer.from(str);
      let result = '';
      for(let b of buf){
          result += b.toString(2);
      }
        return result.match(/(\d{6})/g).map(val=>parseInt(val,2)).map(val=>CHARTS[val]).join('');
    }
    let r = transfer('珠');//54+g
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • Node.js Buffer(缓冲区) JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。但在...
    FTOLsXD阅读 494评论 0 2
  • Buffer是node的核心模块,开发者可以利用它来处理二进制数据,比如文件流的读写、网络请求数据的处理等。 Bu...
    自度君阅读 499评论 0 1
  • 刚跨进高中的大门,便有儿时玩伴告诉我,他有个很帅的初中同学在我班上,但是让我千万不要喜欢他。我对此嗤之以鼻,我是什...
    56fdf6a7f26e阅读 353评论 0 0
  • 人艰不拆,我不说话,就写写 一个月前,编制考试惨败,出不了国,刚毕业没经验,没有合适的工作岗位,被喜欢的人...
    葱白头阅读 976评论 2 9
  • 夕阳的传递方式 无非是 从高一些的树慢慢 滚落到矮一些的树 然后再被更矮的灌木接过去 就这样下楼梯般 一步一步 没...
    伏枥斋阅读 153评论 0 1