最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于Node.js中Buffer的一些你可能不知道的用法

 更新時間:2017年03月28日 11:53:32   作者:老雷  
網(wǎng)上關(guān)于Node.js中Buffer用法的文章有很多,但是感覺還是不夠詳細(xì),所以這篇文章主要介紹了關(guān)于Node.js中Buffer的一些你可能不知道的用法,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。

前言

在大多數(shù)介紹 Buffer 的文章中,主要是圍繞數(shù)據(jù)拼接和內(nèi)存分配這兩方面的。比如我們使用fs模塊來讀取文件內(nèi)容的時候,返回的就是一個 Buffer:

fs.readFile('filename', function (err, buf) {
 // <Buffer 2f 2a 2a 0a 20 2a 20 53 75 ... >
});

在使用net或http模塊來接收網(wǎng)絡(luò)數(shù)據(jù)時,data事件的參數(shù)也是一個 Buffer,這時我們還需要使用Buffer.concat()來做數(shù)據(jù)拼接:

var bufs = [];
conn.on('data', function (buf) {
 bufs.push(buf);
});
conn.on('end', function () {
 // 接收數(shù)據(jù)結(jié)束后,拼接所有收到的 Buffer 對象
 var buf = Buffer.concat(bufs);
});

還可以利用Buffer.toString()來做轉(zhuǎn)換base64或十六進(jìn)制字符的轉(zhuǎn)換,比如:

console.log(new Buffer('hello, world!').toString('base64'));
// 轉(zhuǎn)換成 base64 字符串:aGVsbG8sIHdvcmxkIQ==

console.log(new Buffer('aGVsbG8sIHdvcmxkIQ==', 'base64').toString());
// 還原 base64 字符串:hello, world!

console.log(new Buffer('hello, world!').toString('hex'));
// 轉(zhuǎn)換成十六進(jìn)制字符串:68656c6c6f2c20776f726c6421

console.log(new Buffer('68656c6c6f2c20776f726c6421', 'hex').toString());
// 還原十六進(jìn)制字符串:hello, world!

一般情況下,單個 Node.js 進(jìn)程是有最大內(nèi)存限制的,以下是來自官方文檔中的說明:

What is the memory limit on a node process?

Currently, by default v8 has a memory limit of 512MB on 32-bit systems, and 1.4GB on 64-bit systems. The limit can be raised by setting --max_old_space_size to a maximum of ~1024 (~1 GB) (32-bit) and ~4096 (~4GB) (64-bit), but it is recommended that you split your single process into several workers if you are hitting memory limits.

由于 Buffer 對象占用的內(nèi)存空間是不計算在 Node.js 進(jìn)程內(nèi)存空間限制上的,因此,我們也常常會使用 Buffer 來存儲需要占用大量內(nèi)存的數(shù)據(jù):

// 分配一個 2G-1 字節(jié)的數(shù)據(jù)
// 單次分配內(nèi)存超過此值會拋出異常 RangeError: Invalid typed array length
var buf = new Buffer(1024 * 1024 * 1024 - 1);

以上便是 Buffer 的幾種常見用法。然而,閱讀 Buffer 的 API 文檔時,我們會發(fā)現(xiàn)更多的是readXXX()writeXXX()開頭的 API,具體如下:

  • 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])

這些 API 為在 Node.js 中操作數(shù)據(jù)提供了極大的便利。假設(shè)我們要將一個整形數(shù)值存儲到文件中,比如當(dāng)前時間戳為1447656645380,如果將其當(dāng)作一個字符串存儲時,需要占用 11 字節(jié)的空間,而將其轉(zhuǎn)換為二進(jìn)制存儲時僅需 6 字節(jié)空間即可:

var buf = new Buffer(6);

buf.writeUIntBE(1447656645380, 0, 6);
// <Buffer 01 51 0f 0f 63 04>

buf.readUIntBE(0, 6);
// 1447656645380

在使用 Node.js 編寫一些底層功能時,比如一個網(wǎng)絡(luò)通信模塊、某個數(shù)據(jù)庫的客戶端模塊,或者需要從文件中操作大量結(jié)構(gòu)化數(shù)據(jù)時,以上 Buffer 對象提供的 API 都是必不可少的。

接下來將演示一個使用 Buffer 對象操作結(jié)構(gòu)化數(shù)據(jù)的例子。

操作結(jié)構(gòu)化數(shù)據(jù)

假設(shè)有一個學(xué)生考試成績數(shù)據(jù)庫,每條記錄結(jié)構(gòu)如下:

學(xué)號 課程代碼 分?jǐn)?shù)
XXXXXX XXXX XX

其中學(xué)號是一個 6 位的數(shù)字,課程代碼是一個 4 位數(shù)字,分?jǐn)?shù)最高分為 100 分。

在使用文本來存儲這些數(shù)據(jù)時,比如使用 CSV 格式存儲可能是這樣的:

100001,1001,99
100002,1001,67
100003,1001,88

其中每條記錄占用 15 字節(jié)的空間,而使用二進(jìn)制存儲時其結(jié)構(gòu)將會是這樣:

學(xué)號 課程代碼 分?jǐn)?shù)
3 字節(jié) 2 字節(jié) 1 字節(jié)

每一條記錄僅需要 6 字節(jié)的空間即可,僅僅是使用文本存儲的 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 模塊介紹

上面的例子中,當(dāng)每一條記錄的結(jié)構(gòu)有變化時,我們需要修改readRecord()writeRecord() ,重新計算每一個字段在 Buffer 中的偏移量,當(dāng)記錄的字段比較復(fù)雜時很容易出錯。為此我編寫了lei-proto模塊,它允許你通過簡單定義每條記錄的結(jié)構(gòu)即可生成對應(yīng)的readRecord()`writeRecord()函數(shù)。

首先執(zhí)行以下命令安裝此模塊:

$ npm install lei-proto --save

使用lei-proto模塊后,前文的例子可以改為這樣:

var parsePorto = require('lei-proto');

// 生成指定記錄結(jié)構(gòu)的數(shù)據(jù)編碼/解碼器
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));
}

運行與上文同樣的測試程序,可看到其結(jié)果是一樣的:

<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 } ]

關(guān)于lei-proto模塊的詳細(xì)使用方法可訪問該模塊的主頁瀏覽:https://github.com/leizongmin/node-lei-proto

對此感興趣的讀者也可研究一下其實現(xiàn)原理。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Windows系統(tǒng)下載、部署Node.js與npm環(huán)境的操作方法

    Windows系統(tǒng)下載、部署Node.js與npm環(huán)境的操作方法

    本文介紹在Windows電腦中,下載、安裝并配置Node.js環(huán)境與npm包管理工具的方法,文中通過圖文結(jié)合的方式講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2025-01-01
  • Node 創(chuàng)建第一個服務(wù)器應(yīng)用的操作方法

    Node 創(chuàng)建第一個服務(wù)器應(yīng)用的操作方法

    Node.js是一個基于Chrome V8引擎的JavaScript運行環(huán)境,可以用于構(gòu)建高性能的網(wǎng)絡(luò)應(yīng)用程序,它采用事件驅(qū)動、非阻塞I/O模型,使得程序可以以高效地方式處理并發(fā)請求,這篇文章主要介紹了Node 創(chuàng)建第一個服務(wù)器應(yīng)用,需要的朋友可以參考下
    2024-02-02
  • Node.js實現(xiàn)的簡易網(wǎng)頁抓取功能示例

    Node.js實現(xiàn)的簡易網(wǎng)頁抓取功能示例

    這篇文章主要介紹了Node.js實現(xiàn)的簡易網(wǎng)頁抓取功能示例,本文使用了PhantomJS、node-phantomjs等庫實現(xiàn),需要的朋友可以參考下
    2014-12-12
  • 基于node.js實現(xiàn)微信支付退款功能

    基于node.js實現(xiàn)微信支付退款功能

    在微信開發(fā)中有有付款就會有退款,這樣的功能非常常見,這篇文章主要介紹了node.js實現(xiàn)微信支付退款功能,需要的朋友可以參考下
    2017-12-12
  • 在linux中使用包管理器安裝node.js

    在linux中使用包管理器安裝node.js

    這篇文章主要介紹了在linux中使用包管理器安裝node.js的方法以及具體安裝過程,非常詳細(xì),推薦給大家,有需要的小伙伴參考下吧。
    2015-03-03
  • npm?install?-g?@vue/cli常見問題解決匯總

    npm?install?-g?@vue/cli常見問題解決匯總

    這篇文章主要給大家介紹了關(guān)于npm?install?-g?@vue/cli常見問題解決的相關(guān)資料,文中通過實例代碼將解決的方式介紹的非常詳細(xì),對遇到這個問題的朋友具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-08-08
  • Node實現(xiàn)前端本地開發(fā)接口代理服務(wù)

    Node實現(xiàn)前端本地開發(fā)接口代理服務(wù)

    本文主要介紹了Node實現(xiàn)前端本地開發(fā)接口代理服務(wù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Nest.js系列之Providers及模塊功能使用詳解

    Nest.js系列之Providers及模塊功能使用詳解

    這篇文章主要為大家介紹了Nest.js系列之Providers及模塊功能使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 從零開始在webstorm配置nodejs

    從零開始在webstorm配置nodejs

    WebStorm是作為JS開發(fā)IDE存在的,并且支持流行的Node.js以及JQuery等js框架,下面這篇文章主要給大家介紹了關(guān)于如何從零開始在webstorm配置nodejs的相關(guān)資料,需要的朋友可以參考下
    2024-08-08
  • 詳解Express筆記之動態(tài)渲染HTML(新手入坑)

    詳解Express筆記之動態(tài)渲染HTML(新手入坑)

    這篇文章主要介紹了詳解Express筆記之動態(tài)渲染HTML(新手入坑),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12

最新評論

赤城县| 岳普湖县| 邯郸县| 郸城县| 高清| 昭平县| 和静县| 东丽区| 嘉兴市| 定结县| 延寿县| 樟树市| 嘉鱼县| 柳州市| 蒙阴县| 体育| 民和| 阿尔山市| 武陟县| 侯马市| 清水县| 莎车县| 浮梁县| 四子王旗| 蓬安县| 河池市| 南投市| 平舆县| 盐池县| 庆元县| 类乌齐县| 璧山县| 贡山| 永德县| 宣城市| 兴和县| 监利县| 河间市| 屏边| 新平| 深水埗区|