- Node简介
- 第一个node程序
- module(模块系统)
- npm包管理器
- 模块系统优先级
- 认识http内置模块
- url内置模块
- path内置模块
- fs内置模块
- http模块服务端进阶
- http报文浅析
- url模块进阶
- path模块进阶
- querystring模块进阶
- 了解Buffer和Stream
- os模块
- Buffer模块
- Stream模块
- http模块客户端
- Cookie浅析
Buffer模块进阶
Buffer
类的实例类似于整数数组,但 Buffer
的大小是固定的、且在 V8 堆外分配物理内存。 Buffer
的大小在被创建时确定,且无法调整。
Buffer
类在 Node.js 中是一个全局变量,因此无需使用 require('buffer').Buffer
。
Buffer 类
在计算机内使用二进制表示数据,一个存储空间叫做一个 bit ,只能存储 0 或是 1。 通常,计算机把 8 个bit作为一个存储的单位,称为一个 Byte。于是一个 Byte 可以出现 256 种不同的情况。
一个 Buffer 是一段内存,比如大小为 2(Byte)的buffer,一共有 16 bit ,比如是 00000001 00100011
,可是这样显示太不方便。所以显示这段内存的数据的时候,用其对应的 16 进制就比较方便了,是 01 23
,之所以用 16 进制是因为转换比较方便。
Buffer.alloc(size[, fill[, encoding]])
size
新建的Buffer
期望的长度fill
<string> | <Buffer> | <integer>
用来预填充新建的Buffer
的值。 默认:0
encoding
如果fill
是字符串,则该值是它的字符编码。 默认:'utf8'
分配一个大小为 size
字节的新建的 Buffer
。 如果 fill
为 undefined
,则该 Buffer
会用 0 填充。
例子:
const buf = Buffer.alloc(5);
// 输出: <Buffer 00 00 00 00 00>
console.log(buf);
如果指定了 fill
,则会调用buf.fill(fill)初始化分配的 Buffer
。
例子:
const buf = Buffer.alloc(5, 'a');
// 输出: <Buffer 61 61 61 61 61>
console.log(buf);
如果同时指定了 fill
和 encoding
,则会调用 buf.fill(fill, encoding)
初始化分配的 Buffer
。
Buffer.from(array)
通过一个八位字节的 array
创建一个新的 Buffer
。
例子:
// 创建一个新的包含字符串 'buffer' 的 UTF-8 字节的 Buffer
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
如果 array
不是一个数组,则抛出 TypeError
错误。
类方法:Buffer.from(buffer)
buffer
一个要拷贝数据的已存在的Buffer
将传入的 buffer
数据拷贝到一个新建的 Buffer
实例。
例子:
const buf1 = Buffer.from('buffer');
const buf2 = Buffer.from(buf1);
buf1[0] = 0x61;
// 输出: auffer
console.log(buf1.toString());
// 输出: buffer
console.log(buf2.toString());
如果 buffer
不是一个 Buffer
,则抛出 TypeError
错误。
Buffer.from(string[, encoding])
string
要编码的字符串encoding
<string>
的字符编码。 默认:'utf8'
新建一个包含所给的 JavaScript 字符串 string
的 Buffer
。 encoding
参数指定 string
的字符编码。
例子:
const buf1 = Buffer.from('this is a tést');
// 输出: this is a tést
console.log(buf1.toString());
// 输出: this is a tC)st
console.log(buf1.toString('ascii'));
const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex');
// 输出: this is a tést
console.log(buf2.toString());
如果 string
不是一个字符串,则抛出 TypeError
错误。
Buffer.isBuffer(obj)
- 返回: 如果
obj
是一个Buffer
则返回true
,否则返回false
。
Buffer.isEncoding(encoding)
encoding
一个要检查的字符编码名称- 返回: 如果
encoding
是一个支持的字符编码则返回true
,否则返回false
。
Buffer 与字符编码
Buffer
实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer
实例与普通的 JavaScript 字符串之间进行相互转换。
例子:
const buf = Buffer.from('hello world', 'ascii');
// 输出 68656c6c6f20776f726c64
console.log(buf.toString('hex'));
// 输出 aGVsbG8gd29ybGQ=
console.log(buf.toString('base64'));
Node.js 目前支持的字符编码包括:
'ascii'
- 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。'utf8'
- 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。'utf16le'
- 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。'ucs2'
-'utf16le'
的别名。'base64'
- Base64 编码。当从字符串创建Buffer
时,按照 RFC4648 第 5 章的规定,这种编码也将正确地接受“URL 与文件名安全字母表”。'latin1'
- 一种把Buffer
编码成一字节编码的字符串的方式(由 IANA 定义在 RFC1345 第 63 页,用作 Latin-1 补充块与 C0/C1 控制码)。'binary'
-'latin1'
的别名。'hex'
- 将每个字节编码为两个十六进制字符。
Buffer实例化对象
buf[index]
索引操作符 [index]
可用于获取或设置 buf
中指定 index
位置的八位字节。 这个值指向的是单个字节,所以合法的值范围是的 0x00
至 0xFF
(十六进制),或 0
至 255
(十进制)。
例如:拷贝一个 ASCII 字符串到一个 Buffer
,每次一个字节。
const str = 'Node.js';
const buf = Buffer.allocUnsafe(str.length);
for (let i = 0; i < str.length; i++) {
buf[i] = str.charCodeAt(i);
}
// 输出: Node.js
console.log(buf.toString('ascii'));
buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])
-
target
要比较的Buffer
。 -
targetStart
target
中开始对比的偏移量。 默认:0
-
targetEnd
target
中结束对比的偏移量(不包含)。 当targetStart
为undefined
时忽略。 默认:target.length
-
sourceStart
buf
中开始对比的偏移量。 当targetStart
为undefined
时忽略。 默认:0
-
sourceEnd
中结束对比的偏移量(不包含)。 当targetStart
为undefined
时忽略。 默认:buf.length
-
返回: 比较
buf
与target
,返回表明buf
在排序上是否排在target
之前、或之后、或相同。 对比是基于各自Buffer
实际的字节序列。 -
如果
target
与buf
相同,则返回0
。 -
如果
target
排在buf
前面,则返回1
。 -
如果
target
排在buf
后面,则返回-1
。
例子:
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('BCD');
const buf3 = Buffer.from('ABCD');
// 输出: 0
console.log(buf1.compare(buf1));
// 输出: -1
console.log(buf1.compare(buf2));
// 输出: -1
console.log(buf1.compare(buf3));
// 输出: 1
console.log(buf2.compare(buf1));
// 输出: 1
console.log(buf2.compare(buf3));
// 输出: [ <Buffer 41 42 43>, <Buffer 41 42 43 44>, <Buffer 42 43 44> ]
// (结果相当于: [buf1, buf3, buf2])
console.log([buf1, buf2, buf3].sort(Buffer.compare));
可选的 targetStart
、 targetEnd
、 sourceStart
与 sourceEnd
参数可用于分别在 target
与 buf
中限制对比在指定的范围内。
例子:
const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]);
// 输出: 0
console.log(buf1.compare(buf2, 5, 9, 0, 4));
// 输出: -1
console.log(buf1.compare(buf2, 0, 6, 4));
// 输出: 1
console.log(buf1.compare(buf2, 5, 6, 5));
如果 targetStart < 0
、 sourceStart < 0
、 targetEnd > target.byteLength
或 sourceEnd > source.byteLength
,则抛出 RangeError
错误。
buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
target
要拷贝进的Buffer
。targetStart
target
中开始拷贝进的偏移量。 默认:0
sourceStart
buf
中开始拷贝的偏移量。 当targetStart
为undefined
时忽略。 默认:0
sourceEnd
buf
中结束拷贝的偏移量(不包含)。 当sourceStart
为undefined
时忽略。 默认:buf.length
- 返回: 被拷贝的字节数。拷贝
buf
的一个区域的数据到target
的一个区域,即便target
的内存区域与buf
的重叠。
例子:创建两个 Buffer
实例 buf1
与 buf2
,并拷贝 buf1
中第 16 个至第 19 个字节到 buf2
第 8 个字节起。
const buf1 = Buffer.allocUnsafe(26);
const buf2 = Buffer.allocUnsafe(26).fill('!');
for (let i = 0; i < 26; i++) {
// 97 是 'a' 的十进制 ASCII 值
buf1[i] = i + 97;
}
buf1.copy(buf2, 8, 16, 20);
// 输出: !!!!!!!!qrst!!!!!!!!!!!!!
console.log(buf2.toString('ascii', 0, 25));
例子:创建一个 Buffer
,并拷贝同一 Buffer
中一个区域的数据到另一个重叠的区域。
const buf = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 是 'a' 的十进制 ASCII 值
buf[i] = i + 97;
}
buf.copy(buf, 0, 4, 10);
// 输出: efghijghijklmnopqrstuvwxyz
console.log(buf.toString());
buf.equals(otherBuffer)
otherBuffer
要比较的Buffer
。- 返回: 如果
buf
与otherBuffer
具有完全相同的字节,则返回true
,否则返回false
。
例子:
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('414243', 'hex');
const buf3 = Buffer.from('ABCD');
// 输出: true
console.log(buf1.equals(buf2));
// 输出: false
console.log(buf1.equals(buf3));
buf.fill(value[, offset[, end]][, encoding]
)
value
用来填充buf
的值。offset
开始填充buf
前要跳过的字节数。默认:0
。end
结束填充buf
的位置(不包含)。默认:buf.length
。encoding
如果value
是一个字符串,则这是它的字符编码。默认:'utf8'
。- 返回:
buf
的引用。
如果未指定 offset
和 end
,则填充整个 buf
。 这个简化使得一个 Buffer
的创建与填充可以在一行内完成。
例子:用 ASCII 字符 'h'
填充 Buffer
。
const b = Buffer.allocUnsafe(50).fill('h');
// 输出: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
console.log(b.toString());
value
如果不是一个字符串或整数,则会被强行转换为 uint32
值。
如果 fill()
操作的最后一次写入的是一个多字节字符,则只有字符中适合 buf
的第一个字节会被写入。
例子:用一个两个字节的字符填充 Buffer
。
// 输出: <Buffer c8 a2 c8>
console.log(Buffer.allocUnsafe(3).fill('\u0222'));
buf.includes(value[, byteOffset][, encoding]
)
value
要搜索的值byteOffset
buf
中开始搜索的位置。默认:0
encoding
如果value
是一个字符串,则这是它的字符编码。 默认:'utf8'
- 返回: 如果
buf
找到value
,则返回true
,否则返回false
相当于 buf.indexOf() !== -1
。
例子:
const buf = Buffer.from('this is a buffer');
// 输出: true
console.log(buf.includes('this'));
// 输出: true
console.log(buf.includes('is'));
// 输出: true
console.log(buf.includes(Buffer.from('a buffer')));
// 输出: true
// (97 是 'a' 的十进制 ASCII 值)
console.log(buf.includes(97));
// 输出: false
console.log(buf.includes(Buffer.from('a buffer example')));
// 输出: true
console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8)));
// 输出: false
console.log(buf.includes('this', 4));
buf.indexOf(value[, byteOffset][, encoding]
)
value
要搜索的值byteOffset
buf
中开始搜索的位置。默认:0
encoding
如果value
是一个字符串,则这是它的字符编码。 默认:'utf8'
- 返回:
buf
中value
首次出现的索引,如果buf
没包含value
则返回-1
如果 value
是:
-
字符串,则
value
根据encoding
的字符编码进行解析。 -
Buffer
,则value
会被作为一个整体使用。如果要比较部分Buffer
,可使用buf.slice()
。 -
数值, 则
value
会解析为一个0
至255
之间的无符号八位整数值。
例子:
const buf = Buffer.from('this is a buffer');
// 输出: 0
console.log(buf.indexOf('this'));
// 输出: 2
console.log(buf.indexOf('is'));
// 输出: 8
console.log(buf.indexOf(Buffer.from('a buffer')));
// 输出: 8
// (97 是 'a' 的十进制 ASCII 值)
console.log(buf.indexOf(97));
// 输出: -1
console.log(buf.indexOf(Buffer.from('a buffer example')));
// 输出: 8
console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8)));
// 输出: 4
console.log(utf16Buffer.indexOf('\u03a3', 0, 'ucs2'));
// 输出: 6
console.log(utf16Buffer.indexOf('\u03a3', -4, 'ucs2'));
如果 value
不是一个字符串, 数字, 或者 Buffer
, 该方法会抛出一个 TypeError
异常, 如果 value
是一个数字, 它将会被强制转换成一个有效的 byte 值, 该值介于0到255之间。
如果 byteOffset
不是一个数字, 它将会被强制转换成一个数字。 任何对 NaN
or 0, like {}
, []
, null
or undefined
, 的参数, 将会搜索整个 buffer。 该行为和 String#indexOf()
保持一致。
const b = Buffer.from('abcdef');
// 传入一个不是有效字节的数字
// 输出:2,相当于搜索 99 或 'c'
console.log(b.indexOf(99.9));
console.log(b.indexOf(256 + 99));
// 传入 byteOffset,其值强制转换为 NaN 或 0
// 输出:1,搜索整个 buffer
console.log(b.indexOf('b', undefined));
console.log(b.indexOf('b', {}));
console.log(b.indexOf('b', null));
console.log(b.indexOf('b', []));
如果 value
是一个空字符串或空 Buffer
,并且 byteOffset
小于 buf.length
,返回 byteOffset
。如果 value
是一个空字符串,并且 byteOffset
大于 buf.length
,返回 buf.length
。
buf.keys()
创建并返回一个包含 buf
键名(索引)的迭代器。
例子:
const buf = Buffer.from('buffer');
// 输出:
// 0
// 1
// 2
// 3
// 4
// 5
for (const key of buf.keys()) {
console.log(key);
}
buf.values()
- 返回: 创建并返回一个包含
buf
的值(字节)的迭代器。 当Buffer
使用for..of
时会自动调用该函数。
例子:
const buf = Buffer.from('buffer');
// 输出:
// 98
// 117
// 102
// 102
// 101
// 114
for (const value of buf.values()) {
console.log(value);
}
// 输出:
// 98
// 117
// 102
// 102
// 101
// 114
for (const value of buf) {
console.log(value);
}
buf.entries()
从 buf
的内容中,创建并返回一个 [index, byte]
形式的迭代器。
例子:记录一个 Buffer
全部的内容。
const buf = Buffer.from('buffer');
// 输出:
// [0, 98]
// [1, 117]
// [2, 102]
// [3, 102]
// [4, 101]
// [5, 114]
for (const pair of buf.entries()) {
console.log(pair);
}
buf.lastIndexOf(value[, byteOffset][, encoding]
)
value
要搜索的值byteOffset
buf
中开始搜索的位置。 默认:buf.length
- 1
encoding
如果value
是一个字符串,则这是它的字符编码。 默认:'utf8'
- 返回:
buf
中value
最后一次出现的索引,如果buf
没包含value
则返回-1
与 buf.indexOf()
类似,除了 buf
是从后往前搜索而不是从前往后。
例子:
const buf = Buffer.from('this buffer is a buffer');
// 输出: 0
console.log(buf.lastIndexOf('this'));
// 输出: 17
console.log(buf.lastIndexOf('buffer'));
// 输出: 17
console.log(buf.lastIndexOf(Buffer.from('buffer')));
// 输出: 15
// (97 是 'a' 的十进制 ASCII 值)
console.log(buf.lastIndexOf(97));
// 输出: -1
console.log(buf.lastIndexOf(Buffer.from('yolo')));
// 输出: 5
console.log(buf.lastIndexOf('buffer', 5));
// 输出: -1
console.log(buf.lastIndexOf('buffer', 4));
const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2');
// 输出: 6
console.log(utf16Buffer.lastIndexOf('\u03a3', undefined, 'ucs2'));
// 输出: 4
console.log(utf16Buffer.lastIndexOf('\u03a3', -5, 'ucs2'));
如果 value
不是一个字符串, 数字, 或者 Buffer
, 该方法会抛出一个 TypeError
异常, 如果 value
是一个数字, 它将会被强制转换成一个有效的 byte 值, 该值介于0到255之间。
如果 byteOffset
不是一个数字, 它将会被强制转换成一个数字。 任何对 NaN
or 0, like {}
, []
, null
or undefined
, 的参数, 将会搜索整个 buffer。 该行为和 String#lastIndexOf()
保持一致。
const b = Buffer.from('abcdef');
// 传入一个不是有效字节的数字
// 输出:2,相当于搜索 99 或 'c'
console.log(b.lastIndexOf(99.9));
console.log(b.lastIndexOf(256 + 99));
// 传入 byteOffset,其值强制转换为 NaN
// 输出:1,搜索整个 buffer
console.log(b.lastIndexOf('b', undefined));
console.log(b.lastIndexOf('b', {}));
// 传入 byteOffset,其值强制转换为 0
// 输出:-1,相当于传入 0
console.log(b.lastIndexOf('b', null));
console.log(b.lastIndexOf('b', []));
如果 value
是一个空字符串或者空 Buffer
,返回 byteOffset
。
buf.length
返回 buf
在字节数上分配的内存量。 注意,这并不一定反映 buf
内可用的数据量。
例子:创建一个 Buffer
并写入一个较短的 ASCII 字符串。
const buf = Buffer.alloc(1234);
// 输出: 1234
console.log(buf.length);
buf.write('some string', 0, 'ascii');
// 输出: 1234
console.log(buf.length);
虽然 length
属性不是不可变的,但改变 length
的值可能会导致不确定、不一致的行为。 那些希望修改一个 Buffer
的长度的应用程序应当将 length
视为只读的,且使用 buf.slice()
创建一个新的 Buffer
。
例子:
let buf = Buffer.allocUnsafe(10);
buf.write('abcdefghj', 0, 'ascii');
// 输出: 10
console.log(buf.length);
buf = buf.slice(0, 5);
// 输出: 5
console.log(buf.length);
buf.slice([start[, end]])
start
新建的Buffer
开始的位置。 默认:0
end
新建的Buffer
结束的位置(不包含)。 默认:buf.length
- 返回: 返回一个指向相同原始内存的新建的
Buffer
,但做了偏移且通过start
和end
索引进行裁剪。
指定负的索引会导致切片的生成是相对于 buf
的末尾而不是开头。
例子:
const buf = Buffer.from('buffer');
// 输出: buffe
// (相当于 buf.slice(0, 5))
console.log(buf.slice(-6, -1).toString());
// 输出: buff
// (相当于 buf.slice(0, 4))
console.log(buf.slice(-6, -2).toString());
// 输出: uff
// (相当于 buf.slice(1, 4))
console.log(buf.slice(-5, -2).toString());
buf.toJSON()
- 返回: 返回
buf
的 JSON 格式。 当字符串化一个Buffer
实例时,JSON.stringify()
会隐式地调用该函数。
例子:
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
// 输出: {"type":"Buffer","data":[1,2,3,4,5]}
console.log(json);
const copy = JSON.parse(json, (key, value) => {
return value && value.type === 'Buffer' ?
Buffer.from(value.data) :
value;
});
// 输出: <Buffer 01 02 03 04 05>
console.log(copy);
buf.toString([encoding[, start[, end]]])
encoding
解码使用的字符编码。默认:'utf8'
start
开始解码的字节偏移量。默认:0
end
结束解码的字节偏移量(不包含)。 默认:buf.length
- 返回: 根据
encoding
指定的字符编码解码buf
成一个字符串。start
和end
可传入用于只解码buf
的一部分。
例子:
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 是 'a' 的十进制 ASCII 值
buf1[i] = i + 97;
}
// 输出: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('ascii'));
// 输出: abcde
console.log(buf1.toString('ascii', 0, 5));
const buf2 = Buffer.from('tést');
// 输出: 74c3a97374
console.log(buf2.toString('hex'));
// 输出: té
console.log(buf2.toString('utf8', 0, 3));
// 输出: té
console.log(buf2.toString(undefined, 0, 3));
buf.write(string[, offset[, length]][, encoding]
)
string
要写入buf
的字符串。offset
开始写入string
前要跳过的字节数。默认:0
。length
要写入的字节数。默认:buf.length - offset
。encoding
string
的字符编码。默认:'utf8'
。- 返回: 写入的字节数。
根据 encoding
的字符编码写入 string
到 buf
中的 offset
位置。 length
参数是写入的字节数。 如果 buf
没有足够的空间保存整个字符串,则只会写入 string
的一部分。 只部分解码的字符不会被写入。
例子:
const buf = Buffer.allocUnsafe(256);
const len = buf.write('\u00bd + \u00bc = \u00be', 0);
// 输出: 12 个字节: ½ + ¼ = ¾
console.log(`${len} 个字节: ${buf.toString('utf8', 0, len)}`);
buffer.transcode(source, fromEnc, toEnc)
source
一个Buffer
实例fromEnc
当前编码toEnc
目标编码
将给定的 Buffer
实例从一个字符编码重新编码到另一个字符。 返回一个新的Buffer实例。
如果 fromEnc
或 toEnc
指定的字符串编码无效,或者不允许从 fromEnc
转换为 toEnc
,将抛出异常。
如果给定的字节序列不能在目标编码中充分表示,转码过程将使用替代字符。例如:
const buffer = require('buffer');
const newBuf = buffer.transcode(Buffer.from('€'), 'utf8', 'ascii');
console.log(newBuf.toString('ascii'));
// 输出: '?'
因为欧元符号(€
)不能在 US-ASCII 中表示,所以在转换 Buffer
的时候使用 ?
代替。
注意 buffer
属性是通过 require('buffer')
返回的 buffer
模块,而不是全局 Buffer
或 Buffer
实例的属性。