先上文档连接buffer缓冲器html
在node应用程序中,咱们须要处理网络协议,文件流数据等,在网络流与文件的操做中,还有二进制数据。js中的string明显不能知足这些需求。而buffer对象为咱们提供了操做二进制流数据的能力。node
在引入 TypedArray 以前,JavaScript 语言没有用于读取或操做二进制数据流的机制。 Buffer 类是做为 Node.js API 的一部分引入的,用于在 TCP 流、文件系统操做、以及其余上下文中与八位字节流进行交互。
Buffer 类的实例相似于从 0 到 255 之间的整数数组(其余整数会经过 & 255 操做强制转换到此范围),但对应于 V8 堆外部的固定大小的原始内存分配。 Buffer 的大小在建立时肯定,且没法更改。
Buffer 类在全局做用域中,所以无需使用 require('buffer').Buffer。 --- 摘自文档git
简单的介绍一下Buffer,它的元素为16进制的两位数(即10进制的0-255之间),以下图 github
值得注意的是,在node中,new Buffer('xxx')
和Buffer('xxx')
由于存在着安全性问题,在v6的时候就被废弃了。因此咱们须要使用Buffer.from
或者Buffer.alloc
来替代。这里建议启用ESLint规则no-buffer-constructor
或node/no-deprecated-api
以免意外的不安全Buffer API使用。
那么,Buffer构造函数有什么问题吗?
原来,在node V8以前,new Buffer(50)
将占有50个字节,假如这个做为CGI接受用户的输入,输入500000000,会占用500MB的内存,这么大的内存占用,很快就会内存溢出,致使服务崩溃。而现有的Buffer.from(5000000000)
将会抛出异常。api
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type number 复制代码
Buffer对象的内存分配不是在V8的堆内存中,而是在Node的C++层面实现的内存的申请。当进行小而频繁的Buffer操做时,采用slab(一种动态内存管理的机制)机制进行预先申请和过后分配,使得js到操做系统直接没有过多的内存申请的系统调用。对于大Buffer而言,则是直接使用C++层面提供的内存,无需细腻的分配操做。(区别大小Buffer的界限为8Kb)数组
Buffer对象可与字符串之间相互转换。支持的类型以下:浏览器
'ascii': 仅适用于 7 位 ASCII 数据。此编码速度很快,若是设置则会剥离高位。安全
'utf8': 多字节编码的 Unicode 字符。许多网页和其余文档格式都使用 UTF-8。bash
'utf16le': 2 或 4 个字节,小端序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。markdown
'ucs2': 'utf16le' 的别名。
'base64': Base64 编码。当从字符串建立 Buffer 时,此编码也会正确地接受 RFC 4648 第 5 节中指定的 “URL 和文件名安全字母”。
'latin1': 一种将 Buffer 编码成单字节编码字符串的方法(由 RFC 1345 中的 IANA 定义,第 63 页,做为 Latin-1 的补充块和 C0/C1 控制码)。
'binary': 'latin1' 的别名。
'hex': 将每一个字节编码成两个十六进制的字符。
如下是一个Buffer对象与字符串相互转换的例子
const buf = Buffer.from('hello world', 'ascii'); console.log(buf.toString('hex')); // 打印: 68656c6c6f20776f726c64 console.log(buf.toString('base64')); // 打印: aGVsbG8gd29ybGQ= 复制代码
现有的编码那么多,Buffer只提供了几种,而Buffer.isEncoding
则为咱们提供了编码是否支持转换的能力。对于不支持的类型,咱们只能借助额外的模块来解决了。例如iconv和iconv-lite
const fs = require('fs'); const inputStream = fs.createReadStream('input.txt'); // 建立可读流 const outputStream = fs.createWriteStream('output.txt'); // 建立可写流 inputStream.pipe(outputStream); // 管道读写 复制代码
zlib.js 为 Node.js 的核心库之一,其利用了缓冲区(Buffer)的功能来操做二进制数据流,提供了压缩或解压功能。参考源代码 zlib.js 源码
var http = require('http'); var zlib = require('zlib'); var fs = require('fs'); var filepath = './extra/fileForGzip.html'; var server = http.createServer(function(req, res){ var acceptEncoding = req.headers['accept-encoding']; var gzip; if(acceptEncoding.indexOf('gzip')!=-1){ // 判断是否须要gzip压缩 gzip = zlib.createGzip(); // 记得响应 Content-Encoding,告诉浏览器:文件被 gzip 压缩过 res.writeHead(200, { 'Content-Encoding': 'gzip' }); fs.createReadStream(filepath).pipe(gzip).pipe(res); }else{ fs.createReadStream(filepath).pipe(res); } }); server.listen('3000'); 复制代码
Buffer在node中有着极其重要的地位,流数据的处理都离不开它。在使用时咱们用Buffer.from取代了new Buffer。Buffer的内存分配用到了slab机制进行预先申请和过后分配。在性能上,buffer比string有着更加优异的表现,缘由是流数据自己就是二进制数据,不须要作额外的转换就能够传输。