# Buffer
~~~
稳定度: 3 - 稳定
~~~
纯 JavaScript 对 Unicode 友好但是无法很好地处理二进制数据。当我们面对类似 TCP 流或文件系统时,是需要处理八位流的。Node 有几种操作、创建以及消费八位流的策略。
原始数据保存在 `Buffer` 类的实例中。一个 `Buffer` 实例类似于一个整数数组,但对应者 V8 堆之外的一个原始内存分配区域。一个 `Buffer` 的大小不可变。
`Buffer` 类是一个全局的类,是一个比较罕见的不需要 `require('buffer')` 就可以使用的类。
在Buffers和JavaScript string转换时,需要明确的一个编码方法。下面是一些不同的string编码。
- `'ascii'` - 仅适用 7 bit ASCII 格式数据。这个编码方式非常快速,而且会剥离设置过高的bit。
- `'utf8'` - 多字节编码 Unicode字符。很多网页或者其他文档的编码格式都是使用 UTF-8的。
- `'utf16le'` - 2 或者 4 字节, Little Endian (LE) 编码Unicode字符。 代理对 (U+10000 to U+10FFFF) 是支持的.(BE和LE表示大端和小端,Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端;Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端;下同)
- `'ucs2'` - `'utf16le'`的别名.
- `'base64'` - Base64 字符串编码。
- `'binary'` - 一个将原始2进制数据编码为字符串的方法,仅使用每个字符的前8bits。 这个编码方式已经被弃用而且应该被避免,尽可能的使用`Buffer`对象。这个编码方式将会在未来的Node版本中移除。
- `'hex'` - 把每个byte编码成2个十六进制字符
### 类: Buffer
Buffer 类是一个全局变量类型,用来直接处理2进制数据的。 它能够使用多种方式构建。
### new Buffer(size)
- `size` Number
分配一个新的 buffer 大小是 `size` 的8位字节.
### new Buffer(array)
- `array` Array
分配一个新的 buffer 使用一个8位字节 `array` 数组.
### new Buffer(str, [encoding])
- `str` String类型 - 需要存入buffer的string字符串.
- `encoding` String类型 - 使用什么编码方式,参数可选.
分配一个新的 buffer ,其中包含着给定的 `str`字符串. `encoding` 编码方式默认是:`'utf8'`.
### 类方法: Buffer.isEncoding(encoding)
- `encoding` {String} 用来测试给定的编码字符串
如果给定的编码 `encoding` 是有效的,返回 true,否则返回 false。
### 类方法: Buffer.isBuffer(obj)
- `obj` Object
- 返回: Boolean
测试这个 `obj` 是否是一个 `Buffer`.
### 类方法: Buffer.byteLength(string, [encoding])
- `string` String类型
- `encoding` String类型, 可选参数, 默认是: 'utf8'
- Return: Number类型
将会返回这个字符串真实byte长度。 `encoding` 编码默认是: `'utf8'`. 这个和 `String.prototype.length` 是不一样的,因为那个方法返回这个字符串中有几个字符的数量。 (译者:当用户在写http响应头Cotent-Length的时候,千万记得一定要用 `Buffer.byteLength` 方法,不要使用 `String.prototype.length` )
实例:
~~~
// ½ + ¼ = ¾: 9 characters, 12 bytes
~~~
### 类方法: Buffer.concat(list, [totalLength])
- `list` {Array}数组类型,Buffer数组,用于被连接。
- `totalLength` {Number}类型 上述Buffer数组的所有Buffer的总大小。(译者:注意这里的totalLength不是数组长度是数组里Buffer实例的大小总和)
返回一个保存着将传入buffer数组中所有buffer对象拼接在一起的buffer对象。(译者:有点拗口,其实就是将数组中所有的buffer实例通过复制拼接在一起)
如果传入的数组没有内容,或者 totalLength 参数是0,那将返回一个zero-length的buffer。
如果数组中只有一项,那么这第一项就会被返回。
如果数组中的项多于一个,那么一个新的Buffer实例将被创建。
如果 totalLength 参数没有提供,虽然会从buffer数组中计算读取,但是会增加一个额外的循环来计算它,所以提供一个明确的 totalLength 参数将会更快。
### buf.length
- Number类型
这个buffer的bytes大小。注意这未必是这buffer里面内容的大小。`length` 的依据是buffer对象所分配的内存数值,它不会随着这个buffer对象内容的改变而改变。
~~~
// 1234
// 1234
~~~
### 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.toString([encoding], [start], [end])
- `encoding` String类型, 可选参数, 默认: 'utf8'
- `start` Number类型, 可选参数, 默认: 0
- `end` Number类型, 可选参数, 默认: `buffer.length`
根据 `encoding`参数(默认是 `'utf8'`)返回一个解码的 string 类型。还会根据传入的参数 `start` (默认是`0`) 和 `end` (默认是 `buffer.length`)作为取值范围。
查看上面`buffer.write()` 的例子.
### buf.toJSON()
返回一个 JSON表示的Buffer实例。`JSON.stringify`将会默认调用来字符串序列化这个Buffer实例。
实例:
~~~
console.log(copy);
// <Buffer 74 65 73 74>
~~~
### buf[index]
获取或者设置在指定`index`索引位置的8位字节。这个值是指单个字节,所以这个值必须在合法的范围,16进制的`0x00` 到`0xFF`,或者`0` 到`255`。
例子: 拷贝一个 ASCII 编码的 string 字符串到一个 buffer, 一次一个 byte 进行拷贝:
~~~
// node.js
~~~
### buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])
- `targetBuffer` Buffer 类型对象 - 将要进行拷贝的Buffer
- `targetStart` Number类型, 可选参数, 默认: 0
- `sourceStart` Number类型, 可选参数, 默认: 0
- `sourceEnd` Number类型, 可选参数, 默认: `buffer.length`
进行buffer的拷贝,源和目标可以是重叠的。 `targetStart` 目标开始偏移 和`sourceStart`源开始偏移 默认都是 `0`. `sourceEnd` 源结束位置偏移默认是源的长度 `buffer.length`.
如果传递的值是`undefined`/`NaN` 或者是 out of bounds 超越边界的,就将设置为他们的默认值。(译者:这个默认值下面有的例子有说明)
例子: 创建2个Buffer,然后把将`buf1`的16位到19位 拷贝到 `buf2`中,并且从`buf2`的第8位开始拷贝。
~~~
// !!!!!!!!qrst!!!!!!!!!!!!!
~~~
### 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。
~~~
// abc
// !bc
~~~
### buf.readUInt8(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,读取一个 unsigned 8 bit integer整形。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
实例:
~~~
// 0x3
// 0x4
// 0x23
// 0x42
~~~
### buf.readUInt16LE(offset, [noAssert])
### buf.readUInt16BE(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,使用特殊的 endian字节序格式读取一个 unsigned 16 bit integer。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
实例:
~~~
// 0x0304
// 0x0403
// 0x0423
// 0x2304
// 0x2342
// 0x4223
~~~
### buf.readUInt32LE(offset, [noAssert])
### buf.readUInt32BE(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,使用指定的 endian字节序格式读取一个 unsigned 32 bit integer。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
实例:
~~~
// 0x03042342
// 0x42230403
~~~
### buf.readInt8(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,读取一个 signed 8 bit integer。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
和 `buffer.readUInt8`一样的返回,除非buffer中包含了有作为2的补码的有符号值。
### buf.readInt16LE(offset, [noAssert])
### buf.readInt16BE(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,使用特殊的 endian字节序格式读取一个 signed 16 bit integer。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
和 buffer.readUInt16一样返回,除非buffer中包含了有作为2的补码的有符号值。
### buf.readInt32LE(offset, [noAssert])
### buf.readInt32BE(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,使用指定的 endian字节序格式读取一个 signed 32 bit integer。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
和 buffer.readUInt32一样返回,除非buffer中包含了有作为2的补码的有符号值。
### buf.readFloatLE(offset, [noAssert])
### buf.readFloatBE(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,使用指定的 endian字节序格式读取一个 32 bit float。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
实例:
~~~
// 0x01
~~~
### buf.readDoubleLE(offset, [noAssert])
### buf.readDoubleBE(offset, [noAssert])
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
- Return: Number类型
从这个buffer对象里,根据指定的偏移量,使用指定的 endian字节序格式读取一个 64 bit double。
设置参数 `noAssert`为true表示忽略验证`offset`偏移量参数。 这意味着 `offset`可能会超出buffer的末尾。默认是 `false`。
实例:
~~~
// 0.3333333333333333
~~~
### buf.writeUInt8(value, offset, [noAssert])
- `value` Number类型
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
根据指定的offset偏移量将`value`写入buffer。注意:`value` 必须是一个合法的unsigned 8 bit integer.
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
实例:
~~~
// <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` 必须是一个合法的unsigned 16 bit integer.
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
实例:
~~~
// <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` 必须是一个合法的unsigned 32 bit integer。
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
实例:
~~~
// <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 bit integer。
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
和 `buffer.writeUInt8` 一样工作,除非是把有2的补码的 signed integer 有符号整形写入`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 bit integer。
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
和 `buffer.writeUInt16*` 一样工作,除非是把有2的补码的 signed integer 有符号整形写入`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 bit integer。
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
和 `buffer.writeUInt32*` 一样工作,除非是把有2的补码的 signed integer 有符号整形写入`buffer`。
### buf.writeFloatLE(value, offset, [noAssert])
### buf.writeFloatBE(value, offset, [noAssert])
- `value` Number类型
- `offset` Number类型
- `noAssert` Boolean类型, 可选参数, 默认: false
根据指定的offset偏移量和指定的 endian字节序格式将`value`写入buffer。注意:当`value` 不是一个 32 bit float 类型的值时,结果将是不确定的。
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
实例:
~~~
// <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 bit double 类型的值。
设置参数 `noAssert`为true表示忽略验证`value`和`offset`参数。 这意味着 `value`可能过大,或者`offset`可能会超出buffer的末尾造成`value`被丢弃。 这个参数除了你非常有把握,否则不应该使用它。默认是 `false`。`.
实例:
~~~
// <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类型, 可选参数
- `end` Number类型, 可选参数
使用指定的value来填充这个buffer。如果 `offset` (默认是 `0`) 并且 `end` (默认是 `buffer.length`) 没有明确给出,就会填充整个buffer。 (译者:buf.fill调用的是C语言的memset函数非常高效)
~~~
var b = new Buffer(50);
b.fill("h");
~~~
### buffer.INSPECT_MAX_BYTES
- Number类型, 默认: 50
设置当调用`buffer.inspect()`方法后,多少bytes将会返回。这个值可以被用户模块重写。 (译者:这个值主要用在当我们打印console.log(buf)时,设置返回多少长度内容)
注意这个属性是`require('buffer')`模块返回的。这个属性不是在全局变量Buffer中,也不再buffer的实例里。
### 类: SlowBuffer
返回一个不被池管理的 `Buffer`。
为了避免创建大量独立分配的 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);
});
~~~
请谨慎使用,仅作为开发者频繁观察到他们的应用中过度的内存保留时的*最后*手段。