Detailed explanation of some overlooked usage of Buffer in Node.js
Online articles about Buffer usage in Node.js There are many, but I feel they are still not detailed enough, so this article mainly introduces some usage of Buffer in Node.js that you may not know. The article introduces it in very detail. Friends who need it can refer to it. Let’s take a look together. .
##Preface
In most articles introducing Buffer, they mainly focus on the two aspects of data splicing and memory allocation. When using the fs module toread the contents of a file, a Buffer is returned:
fs.readFile('filename', function (err, buf) { // <Buffer 2f 2a 2a 0a 20 2a 20 53 75 ... > });
event The parameter is also a Buffer. At this time, we also need to use Buffer.concat() for data splicing:
var bufs = []; conn.on('data', function (buf) { bufs.push(buf); }); conn.on('end', function () { // 接收数据结束后,拼接所有收到的 Buffer 对象 var buf = Buffer.concat(bufs); });
Buffer.toString() Convert base64 or hexadecimal characters, such as:
console.log(new Buffer('hello, world!').toString('base64')); // 转换成 base64 字符串:aGVsbG8sIHdvcmxkIQ== console.log(new Buffer('aGVsbG8sIHdvcmxkIQ==', 'base64').toString()); // 还原 base64 字符串:hello, world! console.log(new Buffer('hello, world!').toString('hex')); // 转换成十六进制字符串:68656c6c6f2c20776f726c6421 console.log(new Buffer('68656c6c6f2c20776f726c6421', 'hex').toString()); // 还原十六进制字符串:hello, world!
// 分配一个 2G-1 字节的数据 // 单次分配内存超过此值会抛出异常 RangeError: Invalid typed array length var buf = new Buffer(1024 * 1024 * 1024 - 1);
readXXX() and
writeXXX(), as follows:
- buf.readUIntLE(offset, byteLength[, noAssert])
- buf.readUIntBE(offset, byteLength[, noAssert])
- buf.readIntLE(offset, byteLength[, noAssert])
- buf.readIntBE(offset, byteLength[, noAssert])
- buf.readUInt8(offset[, noAssert])
- buf.readUInt16LE(offset[, noAssert])
- buf.readUInt16BE(offset[ , noAssert])
- buf.readUInt32LE(offset[, noAssert]) ##buf.readUInt32BE(offset[, noAssert])
- buf.readInt8(offset[, noAssert])
- buf.readInt16LE(offset[, noAssert])
- buf.readInt16BE(offset[, noAssert])
- buf.readInt32LE(offset[, noAssert])
- buf. readInt32BE(offset[, noAssert])
- buf.readFloatLE(offset[, noAssert])
- ##buf.readFloatBE(offset[, noAssert ])
- buf.readDoubleLE(offset[, noAssert])
##buf.readDoubleBE(offset[, noAssert])
buf.write(string[, offset][, length][, encoding])
- ##buf.writeUIntLE(value, offset, byteLength[, noAssert ])
- buf.writeUIntBE(value, offset, byteLength[, noAssert])
- buf.writeIntLE(value, offset, byteLength[ , noAssert])
- buf.writeIntBE(value, offset, byteLength[, noAssert])
- buf.writeUInt8(value, offset[ , noAssert])
- buf.writeUInt16LE(value, offset[, noAssert]) ##buf.writeUInt16BE(value, offset[, noAssert ])
- buf.writeUInt32LE(value, offset[, noAssert])
- ##buf.writeUInt32BE(value, offset[, noAssert])
- buf.writeInt8(value, offset[, noAssert])
- buf.writeInt16LE(value, offset[, noAssert])
- buf.writeInt16BE(value, offset[, noAssert])
- buf.writeInt32LE(value, offset[, noAssert])
- buf.writeInt32BE(value, offset[, noAssert])
- buf.writeFloatLE(value, offset[, noAssert])
- buf.writeFloatBE(value, offset[, noAssert])
##buf.writeDoubleLE(value, offset[, noAssert])
buf.writeDoubleBE(value, offset[, noAssert])
- These APIs provide great convenience for operating data in Node.js. Suppose we want to store an integer value into a file. For example, the current timestamp
- is 1447656645380. If it is stored as a string, it will take up 11 bytes of space and convert it to binary. Only 6 bytes of space are needed for storage:
var buf = new Buffer(6); buf.writeUIntBE(1447656645380, 0, 6); // <Buffer 01 51 0f 0f 63 04> buf.readUIntBE(0, 6); // 1447656645380
Copy after login
When using Node.js to write some low-level functions, such as a network communication module, a client module of a database, or need to operate a large number of files from a file When structuring data, the APIs provided by the above Buffer objects are essential. The following will demonstrate an example of using the Buffer object to operate structured data.
操作结构化数据
假设有一个学生考试成绩数据库,每条记录结构如下:
学号 | 课程代码 | 分数 |
---|---|---|
XXXXXX | XXXX | XX |
其中学号是一个 6 位的数字,课程代码是一个 4 位数字,分数最高分为 100 分。
在使用文本来存储这些数据时,比如使用 CSV 格式存储可能是这样的:
100001,1001,99 100002,1001,67 100003,1001,88
其中每条记录占用 15 字节的空间,而使用二进制存储时其结构将会是这样:
学号 | 课程代码 | 分数 |
---|---|---|
3 字节 | 2 字节 | 1 字节 |
每一条记录仅需要 6 字节的空间即可,仅仅是使用文本存储的 40%!下面是用来操作这些记录的程序:
// 读取一条记录 // buf Buffer 对象 // offset 本条记录在 Buffer 对象的开始位置 // data {number, lesson, score} function writeRecord (buf, offset, data) { buf.writeUIntBE(data.number, offset, 3); buf.writeUInt16BE(data.lesson, offset + 3); buf.writeInt8(data.score, offset + 5); } // 写入一条记录 // buf Buffer 对象 // offset 本条记录在 Buffer 对象的开始位置 function readRecord (buf, offset) { return { number: buf.readUIntBE(offset, 3), lesson: buf.readUInt16BE(offset + 3), score: buf.readInt8(offset + 5) }; } // 写入记录列表 // list 记录列表,每一条包含 {number, lesson, score} function writeList (list) { var buf = new Buffer(list.length * 6); var offset = 0; for (var i = 0; i < list.length; i++) { writeRecord(buf, offset, list[i]); offset += 6; } return buf; } // 读取记录列表 // buf Buffer 对象 function readList (buf) { var offset = 0; var list = []; while (offset < buf.length) { list.push(readRecord(buf, offset)); offset += 6; } return list; }
我们可以再编写一段程序来看看效果:
var list = [ {number: 100001, lesson: 1001, score: 99}, {number: 100002, lesson: 1001, score: 88}, {number: 100003, lesson: 1001, score: 77}, {number: 100004, lesson: 1001, score: 66}, {number: 100005, lesson: 1001, score: 55}, ]; console.log(list); var buf = writeList(list); console.log(buf); // 输出 <Buffer 01 86 a1 03 e9 63 01 86 a2 03 e9 58 01 86 a3 03 e9 4d 01 86 a4 03 e9 42 01 86 a5 03 e9 37> var ret = readList(buf); console.log(ret); /* 输出 [ { number: 100001, lesson: 1001, score: 99 }, { number: 100002, lesson: 1001, score: 88 }, { number: 100003, lesson: 1001, score: 77 }, { number: 100004, lesson: 1001, score: 66 }, { number: 100005, lesson: 1001, score: 55 } ] */
lei-proto 模块介绍
上面的例子中,当每一条记录的结构有变化时,我们需要修改readRecord()
和writeRecord()
,重新计算每一个字段在 Buffer 中的偏移量,当记录的字段比较复杂时很容易出错。为此我编写了lei-proto模块,它允许你通过简单定义每条记录的结构即可生成对应的readRecord()
和`writeRecord()
函数。
首先执行以下命令安装此模块:
$ npm install lei-proto --save
使用lei-proto模块后,前文的例子可以改为这样:
var parsePorto = require('lei-proto'); // 生成指定记录结构的数据编码/解码器 var record = parsePorto([ ['number', 'uint', 3], ['lesson', 'uint', 2], ['score', 'uint', 1] ]); function readList (buf) { var list = []; var offset = 0; while (offset < buf.length) { list.push(record.decode(buf.slice(offset, offset + 6))); offset += 6; } return list; } function writeList (list) { return Buffer.concat(list.map(record.encodeEx)); }
运行与上文同样的测试程序,可看到其结果是一样的:
<Buffer 01 86 a1 03 e9 63 01 86 a2 03 e9 58 01 86 a3 03 e9 4d 01 86 a4 03 e9 42 01 86 a5 03 e9 37> [ { number: 100001, lesson: 1001, score: 99 }, { number: 100002, lesson: 1001, score: 88 }, { number: 100003, lesson: 1001, score: 77 }, { number: 100004, lesson: 1001, score: 66 }, { number: 100005, lesson: 1001, score: 55 } ]
总结
The above is the detailed content of Detailed explanation of some overlooked usage of Buffer in Node.js. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



This article will give you an in-depth understanding of the memory and garbage collector (GC) of the NodeJS V8 engine. I hope it will be helpful to you!

The Node service built based on non-blocking and event-driven has the advantage of low memory consumption and is very suitable for handling massive network requests. Under the premise of massive requests, issues related to "memory control" need to be considered. 1. V8’s garbage collection mechanism and memory limitations Js is controlled by the garbage collection machine

Choosing a Docker image for Node may seem like a trivial matter, but the size and potential vulnerabilities of the image can have a significant impact on your CI/CD process and security. So how do we choose the best Node.js Docker image?

The file module is an encapsulation of underlying file operations, such as file reading/writing/opening/closing/delete adding, etc. The biggest feature of the file module is that all methods provide two versions of **synchronous** and **asynchronous**, with Methods with the sync suffix are all synchronization methods, and those without are all heterogeneous methods.

Node 19 has been officially released. This article will give you a detailed explanation of the 6 major features of Node.js 19. I hope it will be helpful to you!

How does Node.js do GC (garbage collection)? The following article will take you through it.

The event loop is a fundamental part of Node.js and enables asynchronous programming by ensuring that the main thread is not blocked. Understanding the event loop is crucial to building efficient applications. The following article will give you an in-depth understanding of the event loop in Node. I hope it will be helpful to you!

The reason why node cannot use the npm command is because the environment variables are not configured correctly. The solution is: 1. Open "System Properties"; 2. Find "Environment Variables" -> "System Variables", and then edit the environment variables; 3. Find the location of nodejs folder; 4. Click "OK".
