Javascript 语言内部使用 Unicode 编码,其对 Unicode 编码支持较好,但确难以处理二进制数据。在网络编程中,如:处理 TCP 流和 fs 文件系统时,需要经常操作字节流。Node.js 提供了Buffer
类,该类可以方便的操作、创建、以及处理字节流。
1. 类: Buffer
Buffer
是一个全局对象,所以不需要require
引用即可使用。
创见Buffer
类实例后,类实例中会存储原始的二进制数据,Buffer
类实例一旦创建后,其大小无法改变。Buffer
的数据存储与数组类似,其数据存储位置位于 V8 堆之外的原始内存区域。
创建一个类似数组的Buffer
,应该注意以下规则:
-
Buffer
是内存拷贝,而不是内存共享。 -
Buffer
占用内存可以理解为一个数组,但其实并不是字节数组。比如,new Uint32Array(new Buffer([1,2,3,4]))
创建了4个Uint32Array
,它的成员为[1,2,3,4]
,而不是[0x1020304]
或[0x4030201]
。
Buffer
与字符串转换
Buffer
类可以和JavaScript String
对象之间进行转换。Buffer
缓存数据转换为字符串时,需要提供一个编码方式。支持的编码方式有:
-
'ascii'
- 7位的 ASCII 数据。这种编码方式非常快,而且会剥离设置过高的bit。 -
'utf8'
- 多字节编码 Unicode 字符。大部分网页和文档使用这类编码方式。 -
'utf16le'
- 2个或4个字节,Little Endian (LE) 编码 Unicode 字符。编码范围 (U+10000 到 U+10FFFF) 。 -
'ucs2'
-'utf16le'
的别名。 -
'base64'
- Base64 字符串编码。 -
'binary'
- 将原始2进制数据编码为字符串。 -
'hex'
- 每个byte编码成2个十六进制字符。
2. Buffer
类的创建
创建Buffer
类可以使用其构造函数new Buffer()
,该函数可以接受多种形式的参数:
new Buffer(size)
-
size
Number 类型
创建一个其大小是size
字节的buffer
实例。size
不能大于1,073,741,824 bytes (1 GB) (32位系统)或不能大于2,147,483,648 bytes (2 GB) (64位系统)。
new Buffer(array)
-
array
Array
通过一个8字节数组创建buffer
实例。
new Buffer(buffer)
-
buffer
Buffer
拷贝一个buffer
实例的数据到另一个buffer
实例。
new Buffer(str[, encoding])
-
str
String,需要存入缓存的字符串 -
encoding
String,可选参数,表示字符串的编码方式
通过传入的str
字符串创建buffer
实例,传入字符串的默认编码方式是'utf8'
。
3. Buffer
类方法
类方法指不需要实例化,通过类名就可以调用的方法。Buffer
类中包含以下类方法:
Buffer.byteLength(string[, encoding])
-
string
String 类型 -
encoding
String 类型,可选参数,默认: 'utf8' - 返回值: Number 类型
返回这个字符串真实byte长度。 encoding
编码默认是: 'utf8'
。这个方法不同与String.prototype.length
,返回是byte长度而不是字符数。在写入HTTP响应头Cotent-Lengthk
时,要使用Buffer.byteLength
方法判断内容长度,而不能使用String.prototype.length
。
Buffer.isEncoding(encoding)
-
encoding
String 类型,表示编码方式的字符串 - 返回值: Boolean
判断encoding
是否是有效的编码方式,是则返回true
,否则返回false
Buffer.isEncoding('hex'); //true Buffer.isEncoding('utf16'); //false
Buffer.isBuffer(obj)
-
obj
Object 类型 - 返回值: Boolean
判断传入对象obj
是否是一个Buffer
。
Buffer.concat(list[, totalLength])
-
list
Array,被连接的Buffer数组 -
totalLength
Number,数组对象里总Buffer大小
将数组中所有的buffer
实例通过复制拼接在一起,返回值是一个新的Buffer
实例。
如果传入的数组没有内容,或者totalLength
参数是0,那将返回一个长度为0的buffer
。如果数组中仅有一项,将返回第一项,如果多于一项将创建一个的buffer
。
Buffer.compare(buf1, buf2)
-
buf1
Buffer -
buf2
Buffer
比较buf1
是在buf2
之前还是之后,与实例方法buf1.compare(buf2)
类似。
var arr = [Buffer('1234'), Buffer('0123')]; arr.sort(Buffer.compare);
4. 类:SlowBuffer
该类可以创建一个不被池管理的Buffer
Node对缓存的管理机制:为了避免创建大量独立分配的Buffer
带来的垃圾回收开销,默认情况下小于 4KB 的空间都是切割自一个较大的独立对象。这种策略既提高了性能也改善了内存使用,因为 V8 不需要跟踪和清理很多Persistent
对象。
当开发者需要将池中一小块数据保留不确定的一段时间,较为妥当的办法是用SlowBuffer
创建一个不被池管理的Buffer
实例并将相应数据拷贝出来。
socket.on('readable', function() { var data = socket.read(); // 为需要保留的数据分配内存 var sb = new SlowBuffer(10); // 将数据拷贝到新的空间中 data.copy(sb, 0, 0, 10); store.push(sb); });
5. 支持ES6 iterator迭代器
Buffer
是可迭代的,可以通过ES6中的for..of
访问其中的数据:
var buf = new Buffer([1, 2, 3]); for (var b of buf) console.log(b) // 1 // 2 // 3