摘要:以和為例,說明中的數(shù)字數(shù)據(jù)如何轉(zhuǎn)換為二進制數(shù)據(jù)。對象用來表示通用的固定長度的原始二進制數(shù)據(jù)緩沖區(qū)。中的數(shù)字數(shù)據(jù)如何轉(zhuǎn)換為二進制數(shù)據(jù)對和有了一個大概的了解,下面讓我們來看下它是如何進行二進制數(shù)據(jù)操作的。
概述
本文主要通過對JavaScript中數(shù)字數(shù)據(jù)與二進制數(shù)據(jù)之間的轉(zhuǎn)換,讓讀者能夠了解在JavaScript中如何對數(shù)字類型(包括但不限于Number類型)進行處理。
二進制數(shù)據(jù)在日常的JavaScript中很少遇到,但是當你使用WebSocket與后端進行數(shù)據(jù)交互時,就有可能會用到二進制的數(shù)據(jù)格式。因此,為了更好的理解本系列中之后發(fā)布的關(guān)于WebSocket傳輸二進制相關(guān)的內(nèi)容,我們有必要了解二進制數(shù)據(jù)在JavaScript中是如何進行操作和存儲的。
本文內(nèi)容主要為:
JavaScript中如何操作與存儲二進制數(shù)據(jù)——ArrayBuffer存儲結(jié)構(gòu)相關(guān)基礎(chǔ)知識以及對應的DataView相關(guān)數(shù)據(jù)類型基礎(chǔ)知識和和API接口,同時對字節(jié)序問題進行介紹。
以Int和Short為例,說明JavaScript中的數(shù)字數(shù)據(jù)如何轉(zhuǎn)換為二進制數(shù)據(jù)。
以Long類型為例,說明JavaScript中如何表示Long類型并且如何將其轉(zhuǎn)換為二進制數(shù)據(jù)。
如何將二進制數(shù)據(jù)中轉(zhuǎn)換為JavaScript中的數(shù)字數(shù)據(jù)。
本文與WebSocket并無太強關(guān)聯(lián),不過作為在WebSocket中傳遞二進制數(shù)據(jù)的基礎(chǔ)知識儲備,因此放入了此系列當中。
如果讀者對WebSocket并不了解,或者說不明白它的使用場景和細節(jié),可以閱讀我的前一篇博客——WebSocket系列之基礎(chǔ)知識入門篇。
如果讀者想了解String類型與二進制之間的處理和轉(zhuǎn)換,可以于都WebSocket系列稍后發(fā)布的文章(文章發(fā)布后會替換此段)。
如果讀者想了解在WebSocket中如何進行二進制的傳遞和解析,可以閱讀WebSocket系列稍后發(fā)布的文章(文章發(fā)布后會替換此段)。
JavaScript中如何存儲和操作二進制數(shù)據(jù)了解了為什么需要使用二進制數(shù)據(jù),我們來看下,在JavaScript中如何存儲和操作二進制數(shù)據(jù)。
ArrayBuffer首先,我們要介紹下在JavaScript中用來存儲二進制數(shù)據(jù)的ArrayBuffer。
ArrayBuffer 對象用來表示通用的、固定長度的原始二進制數(shù)據(jù)緩沖區(qū)。
在MDN的文檔中,我們能夠看到ArrayBuffer的介紹。它是在JavaScript中用來進行二進制數(shù)據(jù)存儲的一種數(shù)據(jù)對象。
下面我們通過一個示例來簡單介紹下ArrayBuffer相關(guān)操作。
const buffer = new ArrayBuffer(8); buffer.byteLength; // 結(jié)果為8
上面的示例通過創(chuàng)建一個長度為8Byte的二進制數(shù)據(jù)緩沖區(qū)。緩沖區(qū)只是一個數(shù)據(jù)存儲的空間,如何對這個存儲空間進行讀取,完全取決于使用者。例如:8個字節(jié)可以當成是2個Int類型的數(shù)據(jù),也可以是一個Long類型的數(shù)據(jù),或者4個Short型的數(shù)據(jù)。
DataView看完了存儲數(shù)據(jù)的ArrayBuffer,我們來看下數(shù)據(jù)讀寫的DataView。
DataView 視圖是一個可以從 ArrayBuffer 對象中讀寫多種數(shù)值類型的底層接口,在讀寫時不用考慮平臺字節(jié)序問題。
這個是在MDN中關(guān)于DataView的介紹。DataView提供了大量的API接口來進行數(shù)據(jù)的讀和寫操作,我們在后三章將會舉例進行說明。但是,首先我們得先看下說明中提到的字節(jié)序問題。
字節(jié)序在現(xiàn)有的計算機體系中,有兩種字節(jié)序:
大端字節(jié)序:高位在前,低位在后。符合人類閱讀習慣。
小端字節(jié)序:低位在前,高位在后。符合計算機讀取習慣。
上面所說的順序均是針對多字節(jié)對象而言,如Int類型,Long類型。以Int類型數(shù)據(jù)0x1234為例,如果是大端字節(jié)序,那么數(shù)據(jù)從人類對數(shù)值的通常寫法上來看就是0x1234;如果是小端字節(jié)序,那么從人類對數(shù)值的通常寫法上來看,應該寫成0x3412。
對于單字節(jié)對象如Byte類型數(shù)據(jù)而言,沒有字節(jié)序一說。
在不同的平臺中,可能使用不同的字節(jié)序,這就是所謂的字節(jié)序問題。DataView所謂的在讀寫時不需要考慮平臺字節(jié)序問題是指:同時使用DataView進行寫入和讀取的數(shù)據(jù)保持一致。
JavaScript中的數(shù)字數(shù)據(jù)如何轉(zhuǎn)換為二進制數(shù)據(jù)對ArrayBuffer和DataView有了一個大概的了解,下面讓我們來看下它是如何進行二進制數(shù)據(jù)操作的。
本章,我以Short類型和Int類型為例,介紹下相關(guān)操作步驟。
let buffer = new ArrayBuffer(6); // 初始化6個Byte的二進制數(shù)據(jù)緩沖區(qū) let dataView = new DataView(buffer); dataView.setInt16(0, 3); // 從第0個Byte位置開始,放置一個數(shù)字為3的Short類型數(shù)據(jù)(占2 Byte) dataView.setInt32(2, 15); // 從第2個Byte位置開始,放置一個數(shù)字為15的Short類型數(shù)據(jù)(占4 Byte)
通過上面的示例,我們一共初始化了6個Byte的存儲空間,使用1個Short類型(占2 Byte)和一個Int類型(占4 Byte)的數(shù)據(jù)進行填充。
DataView還提供了許多的API接口來進行其他數(shù)據(jù)類型的處理,如無符號型,浮點數(shù)等。他們的使用方法和上面介紹的API相同,我們在這里就不一一進行介紹了,希望了解更多API接口的讀者可以查看MDN文檔。
JavaScript中如何表示Long類型并且如何將其轉(zhuǎn)換為二進制數(shù)據(jù)通過DataView提供的API接口,我們知道了如何處理Short類型、Int類型、Float類型和Double類型。那么,如果是對于Long類型這種原生API中沒有提供處理函數(shù)的數(shù)據(jù)類型,我們應該如何處理呢?
首先,我們需要理解Long數(shù)據(jù)類型的結(jié)構(gòu),它是由一個高位的4個Byte和低位的4個Byte組成的數(shù)據(jù)類型。因為Long類型表示的范圍比Number類型大,所以我們在JavaScript中是使用了兩個Number類型(即Int類型)的對象來表示Long類型數(shù)據(jù),相關(guān)的具體細節(jié)可以見我之前的博客Long.js源碼分析與學習。
理解了JavaScript中如何存儲Long類型,我們就知道如果對其進行存儲。
import Long from "long"; let long = Long.fromString("123"); let buffer = new ArrayBuffer(8); let dataView = new DataView(buffer); dataView.setInt32(0, long.high); // 采用大端字節(jié)序放置 dataView.setInt32(4, long.low);
通過上面的示例,我們將一個Long類型的數(shù)據(jù)拆分成了兩個Int類型的數(shù)據(jù),按照大端字節(jié)序放入到了ArrayBuffer中。同理,如果是想按照小端字節(jié)序放置,只需要將數(shù)據(jù)進行部分處理后再放入即可,在此我就不過多介紹了。
如何將二進制數(shù)據(jù)中轉(zhuǎn)換為JavaScript中的數(shù)據(jù)類型當你知道了如何將數(shù)據(jù)轉(zhuǎn)換為ArrayBuffer中存儲的二進制數(shù)據(jù)后,就能夠簡單推測出如何進行反向操作——將數(shù)據(jù)從ArrayBuffer中讀取出來,再轉(zhuǎn)換成JavaScript中常用數(shù)據(jù)類型。
import Long from "long"; let buffer = new ArrayBuffer(14); // 初始化14個Byte的二進制數(shù)據(jù)緩沖區(qū) let dataView = new DataView(buffer); let long = Long.fromString("123"); // 數(shù)據(jù)寫入過程 dataView.setInt16(0, 3); // 從第0個Byte位置開始,放置一個數(shù)字為3的Short類型數(shù)據(jù)(占2 Byte) dataView.setInt32(2, 15); // 從第2個Byte位置開始,放置一個數(shù)字為15的Short類型數(shù)據(jù)(占4 Byte) dataView.setInt32(6, long.high); // 采用大端字節(jié)序放置 dataView.setInt32(10, long.low); // 數(shù)據(jù)讀取過程 let shortNumber = dataView.getInt16(0); let intNumber = dataView.getInt32(2); let longNumber = Long.fromBits(dataView.getInt32(10), dataView.getInt32(6)); // 根據(jù)大端字節(jié)序讀取,該構(gòu)造函數(shù)入?yún)⒁来螢椋旱?6位,高16位
通過上面的示例,我們將一串二進制數(shù)據(jù)轉(zhuǎn)換成為了JavaScript中通用的數(shù)據(jù)類型。
總結(jié)通過使用ArrayBuffer和DataView,我們能夠快速的將數(shù)字數(shù)據(jù)從二進制轉(zhuǎn)換為JavaScript常用數(shù)據(jù)類型如Int、Short等;同時,我們也可以將這些數(shù)據(jù)類型轉(zhuǎn)換為二進制數(shù)據(jù)。有了這些基礎(chǔ)知識,我們就能夠理解在之后的博客中講到的關(guān)于使用WebSocket進行二進制數(shù)據(jù)傳遞的過程和處理邏輯。
下一篇博客我們將介紹String類型相關(guān)的二進制處理與轉(zhuǎn)換操作,有興趣的同學可以關(guān)注留意下相關(guān)內(nèi)容。
部分參考資料阮一峰老師關(guān)于字節(jié)序的介紹
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93799.html
摘要:總結(jié)通過使用和,我們能夠在數(shù)據(jù)和二進制數(shù)據(jù)中進行互相轉(zhuǎn)換。下一篇系列相關(guān)的博客,將會介紹如何通過來向后端傳遞二進制數(shù)據(jù),以及如何處理通過收到的二進制數(shù)據(jù)。 概述 上一篇博客我們說到了如何進行數(shù)字類型(如Short、Int、Long類型)如何在JavaScript中進行二進制轉(zhuǎn)換,如果感興趣的可以可以閱讀本系列第二篇博客——WebSocket系列之JavaScript中數(shù)字數(shù)據(jù)如何轉(zhuǎn)換為...
摘要:本文作為系列的第四篇內(nèi)容,將會用一個簡單的聊天應用把整個傳輸二進制數(shù)據(jù)類型的內(nèi)容連接起來,讓用戶對整個傳輸二進制數(shù)據(jù)的方法有個了解。如何發(fā)送二進制數(shù)據(jù)通過如何設(shè)計一個二進制協(xié)議一章,我們知道了如何定義傳輸?shù)亩M制數(shù)據(jù)格式。 概述 通過前三篇博客,我們能夠了解在通過WebSocket發(fā)送數(shù)據(jù)之前,我們需要傳遞的數(shù)據(jù)是如何變成ArrayBuffer二進制數(shù)據(jù)的;在我們收到二進制數(shù)據(jù)之后,我...
摘要:與此同時,后端服務(wù)的中也有相關(guān)的長連接維持時長設(shè)置。如何快速的恢復連接根據(jù)上面的操作方案,我們會在網(wǎng)絡(luò)異常時斷開連接。 概述 通過前四篇博客,相信讀者對于WebSocket的使用和數(shù)據(jù)(不論是ArrayBuffer還是String)傳輸都有了一個深刻的了解?,F(xiàn)在我們來介紹下,我在使用WebSocket時,連接相關(guān)模塊遇到的一些共性問題,以及我們?nèi)绾谓鉀Q這些問題。 本文作為WebSock...
摘要:概述本文是系列的第一篇,主要介紹相關(guān)的基礎(chǔ)協(xié)議知識和??蛻舳耸盏巾憫?,立即發(fā)起下一次的請求。收到消息通過事件來接收消息。類型則需要傳遞一個對象作為參數(shù),相關(guān)的內(nèi)容也將在本系列第二篇中進行介紹。 概述 本文是WebSocket系列的第一篇,主要介紹WebSocket相關(guān)的基礎(chǔ)協(xié)議知識和API。由于WebSocket的相關(guān)介紹在MDN中分布較亂,初學者不太容易入門,因此通過本文將相關(guān)基礎(chǔ)...
摘要:幀協(xié)議讓我們深入了解下幀協(xié)議。目前可用的值該幀接續(xù)前面一幀的有效載荷。該幀包含二進制數(shù)據(jù)。幀有以下幾類長度表示有效載荷的長度。數(shù)據(jù)分片有效載荷數(shù)據(jù)可以被分成多個獨立的幀。接收端會緩沖這些幀直到位有值。 原文請查閱這里,略有改動,本文采用知識共享署名 3.0 中國大陸許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原...
閱讀 2875·2023-04-25 20:02
閱讀 1477·2021-11-11 16:55
閱讀 652·2021-09-26 09:46
閱讀 6256·2021-09-22 15:55
閱讀 1853·2021-08-09 13:41
閱讀 1599·2019-08-30 15:52
閱讀 2406·2019-08-30 14:13
閱讀 3337·2019-08-26 13:48