Buffer

Node.js Buffer缓冲区免费看

什么是二进制数据、Buffer 与字符编码、Buffer 类的使用、Buffer 类中常用的函数

04-19侠课岛    基础入门       

后端/Node.js/Node.js简明入门 6     0     351

什么是缓冲区呢?你可以将它理解为”临时存储区“的意思,就是暂时存放输入输出数据的一段内存。

在引入TypeArray(类型化数组)之前,JavaScript 语言自身只有字符串数据类型,没有用于读取或操作二进制数据类型。因此 Node.js 提供了一个与 String 对等的全局构造函数 Buffer 来提供对二进制数据的操作。Buffer 类是作为 Node.js API的一部分引入的,用于在 TCP 流、文件系统操作、以及其他上下文中与八位字节流进行交互。

Buffer 与 String 有一个很重要的区别,字符串是只读的,并且对字符串的任何修改得到的都是一个新字符串,原字符串保持不变。至于Buffer,更像是可以做指针操作的C语言数组,可以通过索引下标来修改某个位置的字节。

什么是二进制数据?

二进制是计算机技术中广泛采用的一种数制,二进制数据其实很好理解,就是使用 0 和 1 数码来表示的数据。为了存储或展示一些数据,计算机需要先将这些数据转换为二进制来表示。例如我们想要存储一个42,计算机会先将数字42化为二进制101010表示。

Buffer 与字符编码

Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。

示例

新建 Buffer 实例,可以使用Buffer.from() 构造函数:

const buf = Buffer.from('xkd', 'ascii');

console.log(buf.toString('utf8'));   // 输出 xkd
console.log(buf.toString('binary')); // 输出 xkd
console.log(buf.toString('hex'));    // 输出 784b64
console.log(buf.toString('base64')); // 输出 eGtk

Node.js 目前支持的字符编码有如下所示:

  • ascii :仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
  • utf8 :多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
  • utf16le :2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
  • ucs2 :utf16le的别名。
  • base64 :Base64 编码。
  • latin1: 一种把 Buffer编码成一字节编码的字符串的方式。
  • binary : latin1 的别名。
  • hex :将每个字节编码为两个十六进制字符。

Buffer 类的使用

Buffer 类在全局作用域中,因此无需使用 require('buffer').Buffer

在使用 Buffer创建实例时,由于安全性和可用性问题,不建议使用 Buffer()new Buffer() 构造函数,请改用new Buffer.alloc()Buffer.allocUnsafe()Buffer.from()构造方法。

开发者应将 new Buffer() 构造函数的所有现有用法迁移到这些新的 API:

  • Buffer.from(array):返回一个新的Buffer,其中包含提供的八位字节数组的副本。

  • Buffer.from(arrayBuffer[, byteOffset [, length]]):返回一个新的 Buffer,它与给定的 ArrayBuffer共享相同的已分配内存。

  • Buffer.from(buffer): 返回一个新的 Buffer,其中包含给定 Buffer 的内容的副本。

  • Buffer.from(string[, encoding]):返回一个新的 Buffer,其中包含提供的字符串的副本。

  • Buffer.alloc(size[, fill[, encoding]]):返回一个指定大小的新建的的已初始化的 Buffer。 此方法比 Buffer.allocUnsafe(size) 慢,但能确保新创建的 Buffer 实例永远不会包含可能敏感的旧数据。 如果 size 不是数字,则将会抛出 TypeError。

  • Buffer.allocUnsafe(size)Buffer.allocUnsafeSlow(size): 分别返回一个指定大小的新建的未初始化的 Buffer。 由于 Buffer 是未初始化的,因此分配的内存片段可能包含敏感的旧数据。

    如果 size 小于或等于 Buffer.poolSize 的一半,则 Buffer.allocUnsafe() 返回的 Buffer 实例可能是从共享的内部内存池中分配。 Buffer.allocUnsafeSlow() 返回的实例则从不使用共享的内部内存池。

示例:
var buf = Buffer.from([1, 2, 3, 4, 5]);
console.log(buf)     // <Buffer 01 02 03 04 05>

var buf1 = Buffer.from('hello xkd', 'latin1');
console.log(buf1)    // <Buffer 68 65 6c 6c 6f 20 78 6b 64>

var buf2 = Buffer.from('12');
console.log(buf2)    // <Buffer 31 32> 

var buf3 = Buffer.alloc(1);
console.log(buf3)    // <Buffer 00>

var buf4 = Buffer.alloc(7, 1);
console.log(buf4)    // <Buffer 01 01 01 01 01 01 01>

var buf5 = Buffer.allocUnsafe(10);
console.log(buf5)    // <Buffer 61 2b 4d 82 f5 00 00 00 00 00>

Buffer 类中常用的函数

write函数

buf.write 函数用于将数据写入缓冲区。 语法如下所示:

buf.write(string[, offset[, length]][, encoding])
  • string:写入缓冲区的字符串。
  • offset:缓冲区开始写入之前要跳过的字节数,默认为0 。
  • length:要写入的字节数,默认为buf.length - offset
  • encodingstring 的字符编码,默认为'utf8'。
示例:

根据encoding 指定的字符编码将字符串写入到缓冲区:

buf = Buffer.alloc(5);
len = buf.write("hello xkd");

console.log("写入字节数 : "+  len); //写入字节数 : 5
toString函数

buf.toString 函数用于从缓冲区读取数据。 语法如下所示:

buf.toString([encoding[, start[, end]]])
  • encoding:使用的字符编码,默认为 'utf8' 。
  • start:开始解码的字节偏移量,默认为0。
  • end:结束解码的字节偏移量(不包含),默认值buf.length
示例:

根据 encoding 指定的字符编码将 buf 解码成字符串:

buf = Buffer.alloc(5);  // size为5

for (var i = 0 ; i < 5 ; i++) {
  buf[i] = i + 97;
}

console.log( buf.toString('ascii'));       // abcde
console.log( buf.toString('ascii',0,3));   // abc
console.log( buf.toString('utf8',0,4));    // abcd
console.log( buf.toString(undefined,0,5)); // abcde
toJSON函数

toJSON() 函数用于将 Buffer 转换为 JSON 对象,当字符串化一个 Buffer 实例时,JSON.stringify() 会隐式地调用该 toJSON()。

示例:
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);

console.log(json); //{"type":"Buffer","data":[1,2,3,4,5]}

const copy = JSON.parse(json, (key, value) => {
  return value && value.type === 'Buffer' ?
    Buffer.from(value.data) :
    value;
});

console.log(copy); //<Buffer 01 02 03 04 05>
concat函数

concat() 函数用于缓冲区合并。返回一个合并了 list 中所有 Buffer 实例的新 Buffer。 语法如下所示:

Buffer.concat(list[, totalLength])
  • list :用于合并的Buffer数组或 Uint8Array 数组。如果 list 中没有元素、或 totalLength 为 0,则返回一个长度为 0 的 Buffer
  • totalLength :指定合并后 Buffer 对象的总长度。如果没有提供 totalLength,则计算 list 中的 Buffer 实例的总长度。但是这会导致执行额外的循环用于计算 totalLength,因此如果已知长度,则明确提供长度会更快。
示例:

例如我们使用 concat 函数合并三个Buffer:

var buf1 = Buffer.from(('hello'));
var buf2 = Buffer.from((' '));
var buf3 = Buffer.from(('xkd'));

var new_buf = Buffer.concat([buf1,buf2,buf3]);
console.log("new_buf输出为: " + new_buf.toString());  
// new_buf输出为: hello xkd
compare函数

compare 函数用于缓冲区比较。该方法在 Node.js v0.12.2 版本引入。 语法如下所示:

buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])
  • target:与 buf 对象比较的另外一个Buffer对象。
  • targetStarttarget 中开始对比的偏移量。
  • targetEndtarget 中结束对比的偏移量(不包含)
  • sourceStartbuf 中开始对比的偏移量。
  • sourceEndbuf 中结束对比的偏移量(不包含)。
示例:
var buf1 = Buffer.from('hello');
var buf2 = Buffer.from('xkd');
var result = buf1.compare(buf2);
console.log(result)  // -1

if(result < 0) {
   console.log(buf1 + " 在 " + buf2 + "之前");
}else if(result == 0){
   console.log(buf1 + " 与 " + buf2 + "相同");
}else {
   console.log(buf1 + " 在 " + buf2 + "之后");
}

// hello 在 xkd之前
copy函数

copy函数用于拷贝缓冲区。 语法如下所示:

buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
  • targetBuffer:要拷贝的Buffer对象。
  • targetStart:可选,target 中开始写入之前要跳过的字节数,默认0。
  • sourceStart:可选,buf 中开始拷贝的偏移量,默认0。
  • sourceEnd:可选,buf 中结束拷贝的偏移量(不包含),默认为buffer.length。
示例:

buf2 中某个区域的数据拷贝到 buf1 中的某个区域:

var buf1 = Buffer.from('123456789');
var buf2 = Buffer.from('xkd');

// 将xk插入到buf1中
buf2.copy(buf1, 0, 0, 2);  
console.log(buf1.toString());  // 输出:xk3456789

我们需要注意不同位置的参数表示的含义,例如上面代码中,第一个参数buf1就是创建的Buffer对象,第二个参数0表示从 buf1 中第 0 字节偏移量开始插入。第三个和第四个参数表示拷贝 buf2中第 0 至 2 字节偏移量

slice函数

slice() 函数用于缓冲区裁剪。返回一个新的 Buffer,它引用与原始的 Buffer 相同的内存,但是由 startend 索引进行偏移和裁剪。 语法如下所示:

buf.slice([start[, end]])
  • start:新 Buffer 开始的位置,默认0。
  • end:新 Buffer 结束的位置(不包含),默认buffer.length
示例:

使用slice函数剪裁buf1对象中指定位置的字节,返回一个新的Buffer:

var buf1 = Buffer.from('abcdefg');

// 剪切缓冲区
var buf2 = buf1.slice(0,3);
console.log("buf2的输出结果为: " + buf2.toString());

//buf2的输出结果为: abc
length属性

buf.length属性用于缓冲区长度计算。返回内存中分配给 buf 的字节数。 例如我们创建一个Buffer,并获取Buffer 的长度:

var buf = Buffer.from('xkd');
console.log("buf的长度为: " + buf.length);  

//buf的长度为: 3

本教程图文或视频等内容版权归侠课岛所有,任何机构、媒体、网站或个人未经本网协议授权不得转载、转贴或以其他方式复制发布或发表。

评价

6

本课评分:
  •     非常好
难易程度:
  •     适中的

内容目录


本文索引


|
教程
粉丝
主页

签到有礼

已签到2天,连续签到7天即可领取7天全站VIP

  • 1
    +2 金币
  • 2
    +3 金币
  • 3
    +5 金币
  • 6
    +7 金币
  • 5
    +6 金币
  • 4
    暖心福利
    自选分类VIP ×1天
  • 7
    惊喜大礼

    自选分类VIP ×3天 +20金币
  • 持续签到 +8 金币

金币可以用来做什么?