纯 Javascript 能够很好地支持 Unicode,却不擅长处理二进制数据。与 TCP 数据流或文件系统打交道时,必须处理字节流。Node 有多种方式来操作、建立、消耗字节流。
原始数据存储在 Buffer
类的实例中。一个 Buffer
类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。Buffer
不能调整大小。
Buffer
对象是全局的。
Buffer 和 Javascript 字符串对象之间的转换需要显式地调用编码方法来完成。以下是几种不同的字符串编码:
'ascii'
- 仅用于 7 位 ASCII 字符。这种编码方法非常快,并且会丢弃高位数据(如果有的话)。
'utf8'
- 多字节编码的 Unicode 字符。许多网页和其他文件格式使用 UTF-8。
'ucs2'
- 两个字节,以小尾字节序(little-endian)编码的 Unicode 字符。它只能对 BMP(基本多文种平面,U+0000 - U+FFFF) 范围内的字符编码。
'base64'
- Base64 字符串编码。
'binary'
- 一种将原始二进制数据转换成字符串的编码方式,仅使用每个字符的前 8 位。这种编码方法已经过时,应当尽可能地使用 Buffer
对象。Node 的后续版本将会删除这种编码。
分配一个 size
字节大小的缓冲区。
使用 array
中的字节数据来分配缓冲区。
分配一个包含给定字符串 str
的缓冲区。
使用指定的编码向缓冲区偏移 offset
处写入字符串 string
。返回写入的字节数。如果 buffer
中没有足够的空间来存储整个字符串,字符串的一部分将被写入。使用 'utf8'
编码时,该方法不会截断字符。
示例:向缓冲区写入一个 utf-8 字符串并打印
buf = new Buffer(256);
len = buf.write('\u00bd + \u00bc = \u00be', 0);
console.log(len + " bytes: " + buf.toString('utf8', 0, len));
// 12 bytes: ½ + ¼ = ¾
对缓冲区中从位置 start
到 end
、以 encoding
编码的数据进行解码,并返回该字符串。
参考上文的 buffer.write()
示例。
获取或设置在位置 index
处的字节。该值是不可分割的字节,所以合法的范围是十六进制的 0x00
到 0xFF
,或十进制的 0
到 255
。
示例:复制一个 ASCII 字符串到缓冲区,每次一个字节
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
测试 obj
是否为一个 Buffer
实例。
返回一个字符串的实际字节长度。这跟 String.prototype.length
不太一样,因为 String.prototype.length
返回的是字符串的字符长度。
例如:
str = '\u00bd + \u00bc = \u00be';
console.log(str + ": " + str.length + " characters, " +
Buffer.byteLength(str, 'utf8') + " bytes");
// ½ + ¼ = ¾: 9 characters, 12 bytes
以字节数表示的缓冲区大小。请注意,这不一定是内容的大小。length
指的是给缓冲区分配的内存大小。缓冲区的内容发生改变时,它并不会改变。
buf = new Buffer(1234);
console.log(buf.length);
buf.write("some string", "ascii", 0);
console.log(buf.length);
// 1234
// 1234
在缓冲区之间使用 memcpy() 进行复制。
示例:建立两个缓冲区,然后复制 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!!!!!!!!!!!!!
返回一个新的缓冲区,它和旧缓冲区指向同一块内存,但是从索引 start
到 end
的位置剪裁。
修改新的缓冲区将修改旧缓冲区的内存!
示例:建立一个包含 ASCII 字母表的缓冲区,取得一个切片,然后从原来的缓冲区修改一个字节。
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