文章目录
- Buffer缓冲区
- 1、概述
- 1.1 简介
- 1.2 Buffer模块的结构
- 1.3 Buffer对象的结构
- 1.4 Nodejs中支持的字符编码
- 2、Buffer对象API
- 2.1 创建对象
- 2.1.1 构造方法new Buffer()(已废弃)
- 2.1.2 静态方法Buffer.from()(推荐)
- 2.1.3 静态方法Buffer.alloc(size[, fill[, encoding]])(推荐)
- 2.1.4 Buffer.allocUnsafe(size)
- 2.1.5 Buffer.allocUnsafeSlow(size)
- 2.2 buffer对象的长度
- 2.2.1 buffer.length属性
- 2.2.2 Buffer.byeLength(string[,encoding])
- 2.3 比较buffer
- 2.3.1 Buffer.compare(buf1,buf2)
- 2.3.2 buf.compare(target)
- 2.4 buffer的合并
- Buffer.concat(list[, totalLength])
- 2.5 判断某一个对象是否为buffer实例对象
- Buffer.isBuffer(obj)
- 2.6 给buffer数组排序
- arr.sort(buf1,buf2,...)
- 2.7 判断buffer实例的起源
- buffer.buffer属性
- 2.8 复制
- buf.copy(target)
- 2.9 迭代buffer实例中的所有索引和值
- buf.entries()
- 2.10 比较两个buffer对象的字节是否一致
- buffer.equals(otherBuffer)
- 2.11 用指定的值去取代/填充buffer中的值
- buf.fill(value[, offset[, end]][, encoding])
- 2.12 buf是否包含某一个指定值
- buf.includes(value[, byteOffset][, encoding])
- 2.13 获取指定值出现在buf中的索引位置
- buf.indexof(value)
- buf.lastIndexof()
- 2.14 写入缓冲区
- buf.write(string[, offset[, length]][, encoding])
- 2.15 从缓冲区读取数据
- buf.toString([encoding[, start[, end]]])
- 2.16 将Buffer转为JSON对象
- buf.toJSON()
- 2.17 缓冲区裁剪
- buf.slice([start[, end]])
Buffer是nodejs全局上的一个内置模块,可以直接在不用引入就可以直接调用的模块。
buffer的结构和数组很像,操作的方法也和数组类似。但普通数组类型不能存储音频,视频,图片等二进制文件,Buffer就是用来解决这个问题的。
Buffer能够让javascript直接操作二进制数据,因此Buffer常常和流、管道、IO联系在一起。
当我们需要使用图片、文件、视频这些二进制资源的时候,基本的操作过程就是拿数据,将数据提供给程序并传到具体的应用上,并且应用也并不一定是直接使用传过来的二进制数据,可能还需要换成另一种编码格式的数据,并且在进行转码后这个数据还需要一直保存这种编码格式一段时间,直到应用不再使用这个数据而被系统回收为止。
可以看到,上述过程说到需要“保持这种编码格式一段时间”,其实就是说需要一个存放这个数据的物理资源,也就是说缓存,而Buffer就作为这个缓存。
简单来说buffer就是专门用来存储二进制文件的数组
Buffer作为nodejs全局作用上的一个模块,可以理解为它是全局上的一个属性,这个属性引用着Buffer模块对象,从这角度来说他是一个javascript模块,但javascript自身并不具备直接操作二进制文件的能力,而实际上Buffer在nodejs底层上还有一个C++模块,由于IO操作很好性能,所以Buffer模块的部分性能使用C++实现的。
前面说过,Buffer和数组非常相似,他的元素为16进制的两位数,也就是0~255之间的数值。
let str = "nodejs的学习路径";
let buf = new Buffer(str,'utf-8');
console.log(buf);
//打印结果:
不同编码的字符占用的元素各不相同,utf-8编码汉字占用3个元素,字母和半角标点符号占用1个元素,所以上面的str转成Buffer由21个元素组成。
并且Bufferr也可以和数组一样通过下标访问元素。
let str = "nodejs的学习路径";
let buf = new Buffer(str,'utf-8');
console.log(buf.length); //21
console.log(buf[3]); //101
前面说过,他只会取16进制的数据,也就是0~255之间的数,那么如果不取值的时候结果是什么?如果取得值超过了16进制取值范围会发生什么?
let buf = new Buffer(10);
console.log(buf[10]);//undefined
buf[0] = -10;
buf[1] = -260;
buf[2] = 260;
buf[3] = 515;
console.log(buf) //
可以看到,当不取值时,会默认为00,如果取值超过了256,那么就减n个256,直到这个取值范围在0 ~255之间,例如260就是260-256=4,结果为04;如果取值小于0,那么就加n个256,直到取值范围在0 ~255之间,例如-260就是-260+256+256 = 252
ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
ucs2 - utf16le 的别名。
base64 - Base64 编码。
latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。
binary - latin1 的别名。
hex - 将每个字节编码为两个十六进制字符。
// (1) new Buffer(size)
// 传入一个size表示创建一个size字节大小的buffer实例对象
var buf = new Buffer(10); // 传入一个size表示创建10个字节大小的buffer数组,取值默认全为0
console.log(buf[0]); // 0
console.log(buf[9]); // 0// ============================
// (2)new Buffer(array)
// 传入一个array数组
var arr = [10,20,30,40]
var buf = new Buffer(arr)
console.log(buf); //
console.log(buf[0]); // 10
console.log(buf[1]); // 20// ============================
// (3) new Buffer(arrayBuffer[,byteOffset[,length]])
// 第一个参数:底层ArrayBuffer对象,该参数是必需的。
//第二个参数:视图开始的字节序号,默认从0开始。非必须
//第三个参数:视图包含的数据个数,默认直到本段内存区域结束,非必须
// 传入一个arrayBuffer类型的数据
const bf = new Unit16Array(4);
var buf = new Buffer(bf)
console.log(buf); // // ============================
// (4) new Buffer(buffer)
// 传入一个buffer对象,表示复制一份数据
var buf = new Buffer(10); // 创建一个size=10大小的buffer对象实例
var buf2 = new Buffer(buf) // 复制一份buf实例
console.log(buf2);// ============================
// (5) new Buffer(string[,encoding])
// 传入一个字符串
var buf = new Buffer("name")
console.log(buf); // // 16进制
console.log(buf[0]); // 110 // n对应的Ascii码
console.log(buf.toString()); // name
目前node官网已经不推荐使用buffer的构造函数创建buffer对象了,如果继续使用构造函数创建buffer,则会报如下警告:
[DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
// =======================
// Buffer.from(string[,encoding])
var str = 'Hello World';
// 将一个字符串保存到buffer中
var buf = Buffer.from(str);
console.log(buf);
// 结果:
console.log(buf[0]) // 104 // H对应的ascii码
console.log(buf.toString()); // Hello World// Buffer.from(array)
// 传入一个数组
let arr = [10,20,30,44]
let buf = Buffer.from(arr)
console.log(buf); //
console.log(buf[0]); // 10
console.log(buf[3]); // 44// Buffer.from(arrayBuffer[, byteOffset[, length]])
// 保存一个arrayBuffer类型的数据
const bf = new Uint16Array(2);
bf[0] = 20
bf[1] = 30
const buf = Buffer.from(bf)
console.log(buf); // // Buffer.from(buffer)
const buf1 = Buffer.from('buffer');
const buf2 = Buffer.from(buf1); // 复制一份buf1
console.log(buf1); //
console.log(buf2); // // Buffer.from(Object[, offsetOrEncoding[, length]])
// 存入一个对象
const buf = Buffer.from(new String('this is a test'));
// Prints:
// Buffer.alloc(size[, fill[, encoding]])
// 参数size:buffer数组长度;参数fill:表示用某一个数据填满这个buffer,参数encoding表示编码格式
const buf1 = Buffer.alloc(5);
console.log(buf1); // const buf2 = Buffer.alloc(5,'a')
console.log(buf2); //
返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据。
这个方法比调用 Buffer.alloc() 更快,但返回的 Buffer 实例可能包含旧数据,因此需要使用 fill() 或 write() 重写。
var buf = Buffer.allocUnsafe(10);
buf[0] = 88;
buf[1] = 255; // 11111111
buf[2] = 0xaa;
buf[3] = 256; // 00000000
console.log(buf);
返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据,和allocUnsafe(size)差不多
// =================================
const str = "hello world" // 当存储一个字符串
const arr = [1,2,3,44,44] // 存储一个数组const buf1 = Buffer.from(str)
const buf2 = Buffer.from(arr)console.log(buf1[0]); // 104
console.log(buf2[0]); // 1console.log(str.length); // 11
console.log(buf1.length); // 11
console.log(arr.length); // 5
console.log(buf2.length); // 5
(1)Buffer中都是用二进制形式进行数据的存储,但在输出buffer时是以十六进制形式显示的,当存储的是string类型时,buf[index]输出的是字符对应的ascii码,当存储的是数组类型时,buf[index]输出的是对应数组元素的值
(2)buf.length和str.length虽然结果一样,但含义不一样,buf.length指的是占用内存的大小,也就是说占了11个字节空间,str.length指的是字符串长度,arr.length表示数组的长度
- 获取指定编码格式的字节长度
const str = '\u00bd + \u00bc = \u00be';console.log(str); // ½ + ¼ = ¾
console.log(str.length); // 9 // 字符长度为9
console.log(Buffer.byteLength(str, 'utf8')); // utf8编码格式的字节长度为12
buffer一旦确定长度,就不能改变,并且buffer中的空间是连续的
比较两个buffer实例的大小,比较规则:buf1大,返回1,buf1小,返回-1,相等,返回0
// 比较buffer的大小
const buf1 = Buffer.from('1234');
const buf2 = Buffer.from('0123');let result = Buffer.compare(buf1,buf2) // buf1和buf2比较大小,buf1大,返回1
console.log(result); // 1
比较两个buffer实例的大小,比较规则:buf1大,返回1,buf1小,返回-1,相等,返回0
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('BCD');
console.log(buf1.compare(buf1));
// Prints: 0
console.log(buf1.compare(buf2));
// Prints: -1
参数
- list表示一个集合
- totalLength表示list的长度
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;console.log(totalLength) // 42const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
// 结果就是经过拼接后的buf1,buf2,buf3
Buffer.isBuffer(Buffer.alloc(10)); // true
Buffer.isBuffer(Buffer.from('foo')); // true
Buffer.isBuffer('a string'); // false
Buffer.isBuffer([]); // false
Buffer.isBuffer(new Uint8Array(1024)); // false
const buf1 = Buffer.from('1234');
const buf2 = Buffer.from('0123');const arr = [buf1,buf2]
console.log(arr.sort(Buffer.compare)); // 从小到大排序:[ , ]
const arrayBuffer = new ArrayBuffer(16);
const buffer = Buffer.from(arrayBuffer);console.log(buffer.buffer === arrayBuffer); // 判断buffer是不是起源于arrayBuffer对象
作用:复制一份buf到target中
const buf1 = Buffer.from('0123');
const buf2 = Buffer.alloc(10) // 创建一个10字节大小的bufferconsole.log(buf1); //
console.log(buf2); // buf1.copy(buf2) // 将buf1的数据复制到buf2中console.log(buf1); //
console.log(buf2); //
const buf = Buffer.from('buffer');for (const pair of buf.entries()) {console.log(pair);
}
// Prints:
// [0, 98]
// [1, 117]
// [2, 102]
// [3, 102]
// [4, 101]
// [5, 114]
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('ABC');
const buf3 = Buffer.from('ABCD');console.log(buf1.equals(buf2));
// Prints: true
console.log(buf1.equals(buf3));
// Prints: false
const buf1 = Buffer.allocUnsafe(50).fill('h');
console.log(buf1.toString());
// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
const buf2 = Buffer.alloc(10)
buf2.fill("a",1,5) // 用字符“a”填充下标1~5的元素
console.log(buf2); //
const buf = Buffer.from('this is a buffer');console.log(buf.includes('this')); // 是否包含“this”字符串
// Prints: trueconsole.log(buf.includes(Buffer.from('a buffer'))); // 是否包含“a buffer”字符串
// Prints: trueconsole.log(buf.includes(97));
// Prints: true // 97是a的ascii码,所以也是trueconsole.log(buf.includes(Buffer.from('a buffer example')));
// Prints: falseconsole.log(buf.includes(Buffer.from('a buffer example').slice(0, 8)));
// Prints: trueconsole.log(buf.includes('this', 4));
// Prints: false
作用:获取指定值第一次出现在buf中的索引位置
const buf = Buffer.from('this is a buffer');console.log(buf.indexOf('this'));
// Prints: 0
console.log(buf.indexOf('is'));
// Prints: 2
console.log(buf.indexOf(Buffer.from('a buffer')));
// Prints: 8
console.log(buf.indexOf(97));
// Prints: 8 (97 is the decimal ASCII value for 'a')
console.log(buf.indexOf(Buffer.from('a buffer example')));
// Prints: -1
console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8)));
// Prints: 8
获取指定值最后一次出现在buf中的索引位置
buf = Buffer.alloc(256);
len = buf.write("www.runoob.com"); // 14console.log("写入字节数 : "+ len); //
buf = Buffer.alloc(26);
for (var i = 0 ; i < 26 ; i++) {buf[i] = i + 97;
}console.log( buf.toString('ascii')); // 输出: abcdefghijklmnopqrstuvwxyz
console.log( buf.toString('ascii',0,5)); //使用 'ascii' 编码, 并输出: abcde
console.log( buf.toString('utf8',0,5)); // 使用 'utf8' 编码, 并输出: abcde
console.log( buf.toString(undefined,0,5)); // 使用默认的 'utf8' 编码, 并输出: abcde
当字符串化一个 Buffer 实例时,JSON.stringify() 会隐式地调用该 toJSON()。
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;
});// 输出:
console.log(copy);
返回一个新的缓冲区,它和旧缓冲区指向同一块内存,但是从索引 start 到 end 的位置剪切。
var buffer1 = Buffer.from('runoob');
// 剪切缓冲区
var buffer2 = buffer1.slice(0,2);
console.log(buffer2.toString()); // ru
buffer中其他的方法可以参考nodejs官网