NodeJs 专题
专题目录
您的位置:Js应用 > NodeJs专题 > Node.js Buffer
Node.js Buffer
作者:--    发布时间:2019-11-20
稳定性: 3 - 稳定

纯javascript语言对unicode友好,能够很好地处理unicode编码的字符串数据,但是难以处理二进制数据。在处理tcp流和文件系统时经常需要操作字节流。node提供了一些机制,用于操作、创建、以及消耗字节流。

在node.js中提供了buffer,它可以处理二进制以及非unicode编码的数据。

在buffer类实例化中存储了原始数据。buffer类似于一个整数数组,在v8堆(the v8 heap)原始存储空间给它分配了内存。一旦创建了buffer实例,则无法改变大小。

buffer类是全局对象,所以访问它不必使用require('buffer')

buffers和javascript字符串对象之间转换时需要一个明确的编码方法。下面是字符串的不同编码:

  • 'ascii'- 7位的ascii数据。这种编码方式非常快,它会移除最高位内容。

  • 'utf8'- 多字节编码unicode字符。大部分网页和文档使用这类编码方式。

  • 'utf16le'- 2个或4个字节, little endian (le)编码unicode字符。编码范围(u+10000 到 u+10ffff) 。

  • 'ucs2'-'utf16le'的子集。

  • 'base64' - base64字符编码。

  • 'binary'- 仅使用每个字符的头8位将原始的二进制信息进行编码。在需使用buffer的情况下,应该尽量避免使用这个已经过时的编码方式。这个编码方式将会在未来某个版本中弃用。
  • 'hex'- 每个字节都采用二进制编码。

buffer中创建一个数组,需要注意以下规则:

  1. buffer是内存拷贝,而不是内存共享。

  2. buffer占用内存被解释为一个数组,而不是字节数组。比如,new uint32array(new buffer([1,2,3,4]))创建了4个uint32array,它的成员为 [1,2,3,4],而不是[0x1020304][0x4030201]

注意:node.js v0.8只是简单的引用了array.buffer里的buffer,而不是对其进行克隆(cloning)。

介绍一个高效的方法,arraybuffer#slice()拷贝了一份切片,而buffer#slice()新建了一份。

类: buffer

buffer类是全局变量类型,用来直接处理二进制数据。它能够使用多种方式构建。

new buffer(size)

  • sizenumber类型

分配一个新的size大小单位为8位字节的buffer。

注意:size必须小于kmaxlength,否则将会抛出rangeerror异常。

new buffer(array)

  • arrayarray

使用一个8位字节array数组分配一个新的buffer。

new buffer(buffer)

  • buffer{buffer}

拷贝参数buffer的数据到buffer实例。

new buffer(str[, encoding])

  • str string类型 - 需要编码的字符串。
  • encoding string类型 - 编码方式, 可选。

分配一个新的buffer ,其中包含着传入的str字符串。encoding 编码方式默认为'utf8'

类方法: buffer.isencoding(encoding)

  • encoding {string} 用来测试给定的编码字符串

如果参数编码encoding是有效的,则返回true,否则返回false。

类方法: buffer.isbuffer(obj)

  • obj对象
  • 返回:boolean

obj如果是buffer 返回true,否则返回 false。

类方法: buffer.bytelength(string[, encoding])

  • string string类型
  • encoding string类型,可选的,默认为: 'utf8'
  • 返回:number类型

将会返回这个字符串真实字节长度。 encoding编码默认是:utf8。 这和string.prototype.length不一样,因为那个方法返回这个字符串中字符的数量。

例如:

str = '\u00bd + \u00bc = \u00be';

console.log(str + ": " + str.length + " characters, " +
  buffer.bytelength(str, 'utf8') + " bytes");

// ½ + ¼ = ¾: 9 characters, 12 bytes

类方法: buffer.concat(list[, totallength])

  • list {array} 用来连接的数组
  • totallength {number 类型} 数组里所有对象的总buffer大小

返回一个buffer对象,它将参数buffer数组中所有buffer对象拼接在一起。

如果传入的数组没有内容,或者totallength是0,那将返回一个长度为0的buffer。

如果数组长度为1,返回数组第一个成员。

如果数组长度大于0,将会创建一个新的buffer实例。

如果没有提供totallength参数,会根据buffer数组计算,这样会增加一个额外的循环计算,所以提供一个准确的totallength参数速度更快。

类方法: buffer.compare(buf1, buf2)

  • buf1 {buffer}
  • buf2 {buffer}

buf1.compare(buf2)一样, 用来对数组排序:

var arr = [buffer('1234'), buffer('0123')];
arr.sort(buffer.compare);

buf.length

  • number类型

返回这个buffer的bytes数。注意这未必是buffer里面内容的大小。length是buffer对象所分配的内存数,它不会随着这个buffer对象内容的改变而改变。

buf = new buffer(1234);

console.log(buf.length);
buf.write("some string", 0, "ascii");
console.log(buf.length);

// 1234
// 1234

length不能改变,如果改变length将会导致不可以预期的结果。如果想要改变buffer的长度,需要使用buf.slice来创建新的buffer。

buf = new buffer(10);
buf.write("abcdefghj", 0, "ascii");
console.log(buf.length); // 10
buf = buf.slice(0,5);
console.log(buf.length); // 5

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

  • string string类型 - 写到buffer里
  • offset number类型,可选参数,默认值: 0
  • length number类型,可选参数,默认值:buffer.length - offset
  • encoding string类型,可选参数,默认值: 'utf8'

根据参数offset偏移量和指定的encoding编码方式,将参数string数据写入buffer。offset偏移量默认值是0,encoding编码方式默认是utf8。 length长度是将要写入的字符串的bytes大小。返回number类型,表示写入了多少8位字节流。如果buffer没有足够的空间来放整个string,它将只会只写入部分字符串。length默认是 buffer.length - offset。 这个方法不会出现写入部分字符。

buf = new buffer(256);
len = buf.write('\u00bd + \u00bc = \u00be', 0);
console.log(len + " bytes: " + buf.tostring('utf8', 0, len));

buf.writeuintle(value, offset, bytelength[, noassert])

buf.writeuintbe(value, offset, bytelength[, noassert])

buf.writeintle(value, offset, bytelength[, noassert])

buf.writeintbe(value, offset, bytelength[, noassert])

  • value {number 类型}准备写到buffer字节数
  • offset {number 类型} 0 <= offset <= buf.length
  • bytelength {number 类型} 0 < bytelength <= 6
  • noassert {boolean} 默认值: false
  • 返回: {number 类型}

value写入到buffer里, 它由offsetbytelength决定,支持48位计算,例如:

var b = new buffer(6);
b.writeuintbe(0x1234567890ab, 0, 6);
// <buffer 12 34 56 78 90 ab>

noassert值为true时,不再验证valueoffset 的有效性。 默认是false

buf.readuintle(offset, bytelength[, noassert])

buf.readuintbe(offset, bytelength[, noassert])

buf.readintle(offset, bytelength[, noassert])

buf.readintbe(offset, bytelength[, noassert])

  • offset {number 类型} 0 <= offset <= buf.length
  • bytelength {number 类型} 0 < bytelength <= 6
  • noassert {boolean} 默认值: false
  • 返回: {number 类型}

支持48位以下的数字读取。 例如:

var b = new buffer(6);
b.writeuint16le(0x90ab, 0);
b.writeuint32le(0x12345678, 2);
b.readuintle(0, 6).tostring(16);  // 指定为 6 bytes (48 bits)
// 输出: '1234567890ab'

noassert 值为true时, offset不再验证是否超过buffer的长度,默认为false

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

  • encoding string 类型,可选参数,默认值: 'utf8'
  • start number 类型,可选参数,默认值: 0
  • end number 类型,可选参数,默认值: buffer.length

根据encoding参数(默认是 'utf8')返回一个解码过的string类型。还会根据传入的参数start(默认是 0)和end (默认是 buffer.length)作为取值范围。

buf = new buffer(26);
for (var i = 0 ; i < 26 ; i++) {
  buf[i] = i + 97; // 97 is ascii a
}
buf.tostring('ascii'); // 输出: abcdefghijklmnopqrstuvwxyz
buf.tostring('ascii',0,5); // 输出: abcde
buf.tostring('utf8',0,5); // 输出: abcde
buf.tostring(undefined,0,5); // encoding defaults to 'utf8', 输出 abcde

查看上面buffer.write()例子。

buf.tojson()

返回一个json表示的buffer实例。json.stringify 将会默认调用字符串序列化这个buffer实例。

例如:

var buf = new buffer('test');
var json = json.stringify(buf);

console.log(json);
// '{"type":"buffer","data":[116,101,115,116]}'

var copy = json.parse(json, function(key, value) {
    return value && value.type === 'buffer'
      ? new buffer(value.data)
      : value;
  });

console.log(copy);
// <buffer 74 65 73 74>

buf[index]

获取或设置指定index位置的8位字节。这个值是指单个字节,所以必须在合法的范围取值,16进制的0x00到0xff,或者0到255。

例如: 拷贝一个ascii编码的string字符串到一个buffer,一次一个byte进行拷贝:

str = "node.js";
buf = new buffer(str.length);

for (var i = 0; i < str.length ; i++) {
  buf[i] = str.charcodeat(i);
}

console.log(buf);

// node.js

buf.equals(otherbuffer)

  • otherbuffer {buffer}

如果 thisotherbuffer 拥有相同的内容,返回true。

buf.compare(otherbuffer)

  • otherbuffer {buffer}

返回一个数字,表示 thisotherbuffer 之前,之后或相同。

buf.copy(targetbuffer[, targetstart][, sourcestart][, sourceend])

  • targetbuffer buffer 对象 - buffer to copy into
  • targetstart number 类型,可选参数, 默认值: 0
  • sourcestart number 类型,可选参数, 默认值: 0
  • sourceend number 类型,可选参数, 默认值: buffer.length

buffer拷贝,源和目标可以相同。targetstart目标开始偏移和sourcestart源开始偏移默认都是0。sourceend源结束位置偏移默认是源的长度 buffer.length

例如:创建2个buffer,然后把buf1的16到19位内容拷贝到buf2第8位之后。

buf1 = new buffer(26);
buf2 = new buffer(26);

for (var i = 0 ; i < 26 ; i++) {
  buf1[i] = i + 97; // 97 is ascii a
  buf2[i] = 33; // ascii !
}

buf1.copy(buf2, 8, 16, 20);
console.log(buf2.tostring('ascii', 0, 25));

// !!!!!!!!qrst!!!!!!!!!!!!!

例如: 在同一个buffer中,从一个区域拷贝到另一个区域:

buf = new buffer(26);

for (var i = 0 ; i < 26 ; i++) {
  buf[i] = i + 97; // 97 is ascii a
}

buf.copy(buf, 0, 4, 10);
console.log(buf.tostring());

// efghijghijklmnopqrstuvwxyz

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

  • start number类型,可选参数,默认值: 0
  • end number类型,可选参数,默认值: buffer.length

返回一个新的buffer,这个buffer将会和老的buffer引用相同的内存地址,根据start(默认是 0 ) 和end (默认是 buffer.length ) 偏移和裁剪了索引。 负的索引是从buffer尾部开始计算的。

修改这个新的buffer实例slice切片,也会改变原来的buffer!

例如: 创建一个ascii字母的buffer,进行slice切片,然后修改源buffer上的一个byte。

var buf1 = new buffer(26);

for (var i = 0 ; i < 26 ; i++) {
  buf1[i] = i + 97; // 97 is ascii a
}

var buf2 = buf1.slice(0, 3);
console.log(buf2.tostring('ascii', 0, buf2.length));
buf1[0] = 33;
console.log(buf2.tostring('ascii', 0, buf2.length));

// abc
// !bc

buf.readuint8(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从这个buffer对象里,根据指定的偏移量,读取一个有符号8位整数 整形。

若参数noassert为true将不会验证offset偏移量参数。 如果这样offset 可能会超出buffer的末尾。默认是false

例如:

var buf = new buffer(4);

buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;

for (ii = 0; ii < buf.length; ii++) {
  console.log(buf.readuint8(ii));
}

// 0x3
// 0x4
// 0x23
// 0x42

buf.readuint16le(offset[, noassert])

buf.readuint16be(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从buffer对象里,根据指定的偏移量,使用特殊的endian字节序格式读取一个有符号16位整数。

若参数noassert为true将不会验证offset偏移量参数。 这意味着offset可能会超出buffer的末尾。默认是false

例如:

var buf = new buffer(4);

buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;

console.log(buf.readuint16be(0));
console.log(buf.readuint16le(0));
console.log(buf.readuint16be(1));
console.log(buf.readuint16le(1));
console.log(buf.readuint16be(2));
console.log(buf.readuint16le(2));

// 0x0304
// 0x0403
// 0x0423
// 0x2304
// 0x2342
// 0x4223

buf.readuint32le(offset[, noassert])

buf.readuint32be(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从这个buffer对象里,根据指定的偏移量,使用指定的endian字节序格式读取一个有符号32位整数。

若参数noassert为true将不会验证offset偏移量参数。 这意味着offset可能会超出buffer的末尾。默认是false

例如:

var buf = new buffer(4);

buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;

console.log(buf.readuint32be(0));
console.log(buf.readuint32le(0));

// 0x03042342
// 0x42230403

buf.readint8(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从这个buffer对象里,根据指定的偏移量,读取一个signed 8位整数。

若参数noassert为true将不会验证offset偏移量参数。 这意味着offset可能会超出buffer的末尾。默认是false

返回和buffer.readuint8一样,除非buffer中包含了有作为2的补码的有符号值。

buf.readint16le(offset[, noassert])

buf.readint16be(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从这个buffer对象里,根据指定的偏移量,使用特殊的endian格式读取一个signed 16位整数。

若参数noassert为true将不会验证 offset 偏移量参数。 这意味着offset可能会超出buffer的末尾。默认是false

返回和buffer.readuint16一样,除非buffer中包含了有作为2的补码的有符号值。

buf.readint32le(offset[, noassert])

buf.readint32be(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从这个buffer对象里,根据指定的偏移量,使用指定的endian字节序格式读取一个signed 32位整数。

若参数noassert为true将不会验证offset偏移量参数。 这意味着offset可能会超出buffer的末尾。默认是false

buffer.readuint32一样返回,除非buffer中包含了有作为2的补码的有符号值。

buf.readfloatle(offset[, noassert])

buf.readfloatbe(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从这个buffer对象里,根据指定的偏移量,使用指定的endian字节序格式读取一个32位浮点数。

若参数noassert为true将不会验证offset偏移量参数。 这意味着offset可能会超出buffer的末尾。默认是false

例如:

var buf = new buffer(4);

buf[0] = 0x00;
buf[1] = 0x00;
buf[2] = 0x80;
buf[3] = 0x3f;

console.log(buf.readfloatle(0));

// 0x01

buf.readdoublele(offset[, noassert])

buf.readdoublebe(offset[, noassert])

  • offset number类型
  • noassert boolean,可选参数, 默认值: false
  • 返回: number类型

从这个buffer对象里,根据指定的偏移量,使用指定的endian字节序格式读取一个64位double。

若参数noassert为true将不会验证offset偏移量参数。 这意味着offset可能会超出buffer 的末尾。默认是false

例如:

var buf = new buffer(8);

buf[0] = 0x55;
buf[1] = 0x55;
buf[2] = 0x55;
buf[3] = 0x55;
buf[4] = 0x55;
buf[5] = 0x55;
buf[6] = 0xd5;
buf[7] = 0x3f;

console.log(buf.readdoublele(0));

// 0。3333333333333333

buf.writeuint8(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量将value写入buffer。注意:value必须是一个合法的有符号 8 位整数。

若参数noassert为true将不会验证offset 偏移量参数。 这意味着value可能过大,或者offset可能会超出buffer的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则不要使用。默认是false

例如:

var buf = new buffer(4);
buf.writeuint8(0x3, 0);
buf.writeuint8(0x4, 1);
buf.writeuint8(0x23, 2);
buf.writeuint8(0x42, 3);

console.log(buf);

// <buffer 03 04 23 42>

buf.writeuint16le(value, offset[, noassert])

buf.writeuint16be(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量和指定的endian格式将value写入buffer。注意:value必须是一个合法的有符号16位整数。

若参数noassert为true将不会验证valueoffset偏移量参数。 这意味着value可能过大,或者offset可能会超出buffer的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是false

例如:

var buf = new buffer(4);
buf.writeuint16be(0xdead, 0);
buf.writeuint16be(0xbeef, 2);

console.log(buf);

buf.writeuint16le(0xdead, 0);
buf.writeuint16le(0xbeef, 2);

console.log(buf);

// <buffer de ad be ef>
// <buffer ad de ef be>

buf.writeuint32le(value, offset[, noassert])

buf.writeuint32be(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量和指定的endian格式将value写入buffer。注意:value必须是一个合法的有符号32位整数。

若参数noassert为true将不会验证valueoffset偏移量参数。 这意味着value可能过大,或者offset可能会超出buffer的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是false

例如:

var buf = new buffer(4);
buf.writeuint32be(0xfeedface, 0);

console.log(buf);

buf.writeuint32le(0xfeedface, 0);

console.log(buf);

// <buffer fe ed fa ce>
// <buffer ce fa ed fe>

buf.writeint8(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量将value写入buffer。注意:value必须是一个合法的signed 8位整数。

若参数noassert为true将不会验证valueoffset偏移量参数。这意味着value可能过大,或者offset可能会超出buffer的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是false

buffer.writeuint8一样工作,除非是把有2的补码的有符号整数有符号整形写入buffer。

buf.writeint16le(value, offset[, noassert])

buf.writeint16be(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量和指定的endian格式将value写入buffer。注意:value必须是一个合法的signed 16位整数。

若参数noassert为true将不会验证valueoffset偏移量参数。 这意味着value可能过大,或者offset可能会超出buffer的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是false

buffer.writeuint16*一样工作,除非是把有2的补码的有符号整数 有符号整形写入buffer

buf.writeint32le(value, offset[, noassert])

buf.writeint32be(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量和指定的endian格式将value写入buffer。注意:value必须是一个合法的signed 32位整数。

若参数noassert为true将不会验证valueoffset偏移量参数。 这意味着value可能过大,或者offset可能会超出 buffer 的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是false

buffer.writeuint32*一样工作,除非是把有2的补码的有符号整数、有符号整形写入buffer。

buf.writefloatle(value, offset[, noassert])

buf.writefloatbe(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量和指定的endian格式将value写入buffer。注意:当value不是一个32位浮点数类型的值时,结果将是不确定的。

若参数noassert为true将不会验证valueoffset偏移量参数。这意味着value可能过大,或者offset可能会超出buffer的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是false

例如:

var buf = new buffer(4);
buf.writefloatbe(0xcafebabe, 0);

console.log(buf);

buf.writefloatle(0xcafebabe, 0);

console.log(buf);

// <buffer 4f 4a fe bb>
// <buffer bb fe 4a 4f>

buf.writedoublele(value, offset[, noassert])

buf.writedoublebe(value, offset[, noassert])

  • value number类型
  • offset number类型
  • noassert boolean,可选参数, 默认值: false

根据传入的offset偏移量和指定的endian格式将value写入buffer。注意:value必须是一个有效的64位double类型的值。

若参数noassert为true将不会验证valueoffset偏移量参数。 这意味着value可能过大,或者offset可能会超出buffer的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是false

例如:

var buf = new buffer(8);
buf.writedoublebe(0xdeadbeefcafebabe, 0);

console.log(buf);

buf.writedoublele(0xdeadbeefcafebabe, 0);

console.log(buf);

// <buffer 43 eb d5 b7 dd f9 5f d7>
// <buffer d7 5f f9 dd b7 d5 eb 43>

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

  • value
  • offset number类型, optional
  • end number类型, optional

使用指定的value来填充这个buffer。如果没有指定offset (默认是 0) 并且end(默认是buffer.length) ,将会填充整个buffer。

var b = new buffer(50);
b.fill("h");

buffer.inspect_max_bytes

  • number 类型,默认值: 50

设置当调用buffer.inspect()方法后,将会返回多少bytes 。用户模块重写这个值可以。

注意这个属性是require('buffer')模块返回的。这个属性不是在全局变量buffer中,也不在buffer的实例里。

类: slowbuffer

返回一个不被池管理的buffer

大量独立分配的buffer容易带来垃圾,为了避免这个情况,小于4kb的空间都是切割自一个较大的独立对象。这种策略既提高了性能也改善了内存使用率。v8不需要跟踪和清理过多的persistent对象。

当开发者需要将池中一小块数据保留一段时间,比较好的办法是用slowbuffer创建一个不被池管理的buffer实例,并将相应数据拷贝出来,如下所示:

// need to keep around a few small chunks of memory
var store = [];

socket。on('readable', function() {
  var data = socket。read();
  // allocate for retained data
  var sb = new slowbuffer(10);
  // copy the data into the new allocation
  data。copy(sb, 0, 0, 10);
  store。push(sb);
});

请谨慎使用,仅作为经常发现他们的应用中过度的内存保留时的最后手段。

网站声明:
本站部分内容来自网络,如您发现本站内容
侵害到您的利益,请联系本站管理员处理。
联系站长
373515719@qq.com
关于本站:
编程参考手册