深入Node模块Buffer-学会操作二进制

Buffer 作为 nodejs 中重要的概念和功能,为开发者提供了操作二进制的能力。本文记录了几个问题,来加深对 Buffer 的理解和使用:
认识缓冲器 如何申请堆外内存 如何计算字节长度 如何计算字节长度 如何转换字符编码 理解共享内存与拷贝内存
认识 Buffer(缓冲器)
Buffer 是 nodejs 核心 API,它提供我们处理二进制数据流的功能。Buffer 的使用和 ES2017 的 Uint8Array 非常相似,但由于 node 的特性,专门提供了更深入的 api。
Uint8Array 的字面意思就是:8 位无符号整型数组。一个字节是 8bit,而字节的表示也是由两个 16 进制(4bit)的数字组成的。
const buf = Buffer.alloc(1);
console.log(buf); // output: <Buffer 00>
如何申请堆外内存
Buffer 可以跳出 nodejs 对堆内内存大小的限制。nodejs12 提供了 4 种 api 来申请堆外内存:
Buffer.from()Buffer.alloc(size[, fill[, encoding]])Buffer.allocUnsafe(size)Buffer.allocUnsafeSlow(size)
Buffer.alloc vs Buffer.allocUnsafe
在申请内存时,可能这片内存之前存储过其他数据。如果不清除原数据,那么会有数据泄漏的安全风险;如果清除原数据,速度上会慢一些。具体用哪种方式,根据实际情况定。
Buffer.alloc:申请指定大小的内存,并且清除原数据,默认填充 0 Buffer.allocUnsafe:申请指定大小内存,但不清除原数据,速度更快
根据提供的 api,可以手动实现一个alloc:
function pollifyAlloc(size, fill = 0, encoding = "utf8") {
const buf = Buffer.allocUnsafe(size);
buf.fill(fill, 0, size, encoding);
return buf;
}
Buffer.allocUnsafe vs Buffer.allocUnsafeSlow
从命名上可以直接看出效果,Buffer.allocUnsafeSlow更慢。因为当使用 Buffer.allocUnsafe 创建新的 Buffer 实例时,如果要分配的内存小于 4KB,则会从一个预分配的 Buffer 切割出来。 这可以避免垃圾回收机制因创建太多独立的 Buffer 而过度使用。
这种方式通过消除跟踪和清理的需要来改进性能和内存使用。
如何计算字节长度
利用 Buffer,可以获得数据的真实所占字节。例如一个汉字,它的字符长度是 1。但由于是 utf8 编码的汉字,所以占用 3 个字节。
直接利用Buffer.byteLength()可以获得字符串指定编码的字节长度:
const str = "本文原文地址: xxoo521.com";
console.log(Buffer.byteLength(str, "utf8")); // output: 31
console.log(str.length); // output: 19
也可以直接访问 Buffer 实例的 length 属性(不推荐):
console.log(Buffer.from(str, "utf8").length); // output: 31
如何转换字符编码
Nodejs 当前支持的编码格式有:ascii、utf8、utf16le、ucs2、base64、latin1、binary、hex。其他编码需要借助三方库来完成。
下面,是用Buffer.from()和buf.toString()来封装的 nodejs 平台的编码转换函数:
function trans(str, from = "utf8", to = "utf8") {
const buf = Buffer.from(str, from);
return buf.toString(to);
}
// output: 5Y6f5paH5Zyw5Z2AOiB4eG9vNTIxLmNvbQ==
console.log(trans("原文地址: xxoo521.com", "utf8", "base64"));
共享内存与拷贝内存
在生成 Buffer 实例,操作二进制数据的时候,千万要注意接口是基于共享内存,还是基于拷贝底层内存。
例如对于生成 Buffer 实例的from(),不同类型的参数,nodejs 底层的行为是不同的。
为了更形象地解释,请看下面两段代码。
代码 1:
const buf1 = Buffer.from("buffer");
const buf2 = Buffer.from(buf1); // 拷贝参数中buffer的数据到新的实例
buf1[0]++;
console.log(buf1.toString()); // output: cuffer
console.log(buf2.toString()); // output: buffer
代码 2:
const arr = new Uint8Array(1);
arr[0] = 97;
const buf1 = Buffer.from(arr.buffer);
console.log(buf1.toString()); // output: a
arr[0] = 98;
console.log(buf1.toString()); // output: b
在第二段代码中,传入Buffer.from的参数类型是arrayBuffer。因此Buffer.from仅仅是创建视图,而不是拷贝底层内存。buf1 和 arr 的内存是共享的。
在操作 Buffer 的过程中,需要特别注意共享和拷贝的区别,发生错误比较难排查。
参考链接
Buffer 文档 MDN Uint8Array How to use Buffers in Node.js Do you want a better understanding of Buffer in Node.js? Check this out. An Introduction to Buffer in Node.js
最后
觉得不错,帮忙点个推荐呗,您的支持是对我最大的激励 欢迎我的公众号:「心谭博客」,只专注于前端 + 算法的原创分享
深入Node模块Buffer-学会操作二进制的更多相关文章
- node.js—Buffer类(二进制数据处理模块)
Buffer类概述 一个用于更好的操作二进制数据的类 我们在操作文件或者网络数据的时候,其实操作的就是二进制数据流 Node为我们提供了一个更加方便的去操作这种数据流的类 Buffer,他是一个全局的 ...
- node的buffer模块
Buffer这块很早前就想留一篇笔记.前端JS处理buffer的场景其实并不多,虽然后来基于webGL与显卡通信的需求增加了二进制数组,但毕竟相对小众. Buffer的含义是,在数据传输时用内存中的一 ...
- Node.js缓冲模块Buffer
前言 Javascript是为浏览器而设计的,能很好的处理unicode编码的字符串,但对于二进制或非unicode编码的数据就显得无能为力. Node.js继承Javascript的语言特性,同时又 ...
- Node.js之使用Buffer类处理二进制数据
Node.js之使用Buffer类处理二进制数据 Buffer类可以在处理TCP流或文件流时处理二进制数据,该类用来创建一个专门存放二进制数据的缓存区. 1. 创建Buffer对象 1.1 直接创建: ...
- node使用buffer生成图片
buffer是node里的一个模块,这个模块的出现是因为js没有阅读和操作二进制数据流而出现的 buffer是什么及作用? Buffer顾名思义叫缓冲区,用于存储速度不同步的设备或优先级不同的设备之间 ...
- 模块机制 之commonJs、node模块 、AMD、CMD
在其他高级语言中,都有模块中这个概念,比如java的类文件,PHP有include何require机制,JS一开始就没有模块这个概念,起初,js通过<script>标签引入代码的方式显得杂 ...
- Node.js Buffer(缓冲区)
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型. 但在处理像TCP流或文件流时,必须使用到二进制数据.因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门 ...
- node 之 Buffer 笔记
1. Buffer 相关 js 最初是被设计来处理 html的,因此它不善于处理二进制数据,只有数值和字符串类型.而 node 是基于 js 的,因为 node 需要实现一些譬如数据库通信.操作图像及 ...
- nodeJS-使用buffer类处理二进制数据
使用buffer类处理二进制数据 在客户端javascript脚本代码中,对于二进制数据并没有提供一个很好的支持.然后在nodejs中需要处理像TCP流或文件流时,必须要处理二进制数据.因此在node ...
随机推荐
- JAVA兼职架构师
在一些小企业或者公司人力不足的时候,经常会出现一个人干多个人的活.开发可能会干架构.测试.运维,一些小项目可能需要一个人完成.我把这些角色合并在一起称之为兼职架构师. 我用我的经历来说说兼职架构师的需 ...
- jQuery的使用及关于框架造型 专题
Introduction 正如jQuery所宣称的一样,Write Less, Do More.很多时候我们喜欢用它来解决问题.但增加一个库必然意味着更大的网络负担,意味着更高的页面初始载入时间.并且 ...
- Windows 服务安装与卸载 (通过 Sc.exe)
1. 安装 新建文本文件,重命名为 ServiceInstall.bat,将 ServiceInstall.bat 的内容替换为: sc create "Verity Platform De ...
- CP防火墙导入.csv格式的对象
Step1:将.csv格式的对象上传到管理服务器,本例为/home/admin目录 [Expert@SZ-OFFICE-SMT:0]# pwd/home/admin[Expert@SZ-OFFICE- ...
- 【Docker】删除镜像
删除镜像:docker rmi [OPTIONS] IMAGE [IMAGE...] 1.删除所有未被 tag 标记和未被容器使用的镜像: docker image prune 2.删除所有未被容器使 ...
- E420笔记本升级固态硬盘
后壳比较好拆 机械硬盘盒 这里 可费了好大劲 才 拧开这 4个螺丝 光驱支架买的这个38-5rmb,京东自提 以前不知道的一件事: 原来的光驱挡板要自己拆下来换到新买的光驱支架上面 ...
- [DevExpress]treeList1背景色设置与自定义图标
为了和系统界面一致改成透明色: treeList1.BackColor = Color.Transparent; treeList1.Appearance.Empty.BackColor = Colo ...
- 机器学习- Numpy基础 吐血整理
Numpy是专门为数据科学或者数据处理相关的需求设计的一个高效的组件.听起来是不是挺绕口的,其实简单来说就2个方面,一是Numpy是专门处理数据的,二是Numpy在处理数据方面很牛逼(肯定比Pytho ...
- 组长组Beta阶段贡献分配规则
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/9910“ “组长”组贡献分分配规则: 组里五位成员分别有入团队贡献分10分 ...
- 洛谷$P3959\ [NOIp2017]$ 宝藏 状压$dp$
正解:状压$dp$ 解题报告: 传送门$QwQ$ $8102$年的时候就想搞这题了,,,$9102$了$gql$终于开始做这题了$kk$ 发现有意义的状态只有当前选的点集和深度,所以设$f_{i,j} ...