WebSocket系列之JavaScript數字數據如何轉換爲二進制數據

概述

本文主要經過對JavaScript中數字數據與二進制數據之間的轉換,讓讀者可以瞭解在JavaScript中如何對數字類型(包括但不限於Number類型)進行處理。javascript

二進制數據在平常的JavaScript中不多遇到,可是當你使用WebSocket與後端進行數據交互時,就有可能會用到二進制的數據格式。所以,爲了更好的理解本系列中以後發佈的關於WebSocket傳輸二進制相關的內容,咱們有必要了解二進制數據在JavaScript中是如何進行操做和存儲的。html

本文內容主要爲:java

  • JavaScript中如何操做與存儲二進制數據——ArrayBuffer存儲結構相關基礎知識以及對應的DataView相關數據類型基礎知識和和API接口,同時對字節序問題進行介紹。
  • 以Int和Short爲例,說明JavaScript中的數字數據如何轉換爲二進制數據。
  • 以Long類型爲例,說明JavaScript中如何表示Long類型而且如何將其轉換爲二進制數據。
  • 如何將二進制數據中轉換爲JavaScript中的數字數據。

本文與WebSocket並沒有太強關聯,不過做爲在WebSocket中傳遞二進制數據的基礎知識儲備,所以放入了此係列當中。後端

若是讀者對WebSocket並不瞭解,或者說不明白它的使用場景和細節,能夠閱讀個人前一篇博客——WebSocket系列之基礎知識入門篇函數

若是讀者想了解String類型與二進制之間的處理和轉換,能夠於都WebSocket系列稍後發佈的文章(文章發佈後會替換此段)。源碼分析

若是讀者想了解在WebSocket中如何進行二進制的傳遞和解析,能夠閱讀WebSocket系列稍後發佈的文章(文章發佈後會替換此段)。post

JavaScript中如何存儲和操做二進制數據

瞭解了爲何須要使用二進制數據,咱們來看下,在JavaScript中如何存儲和操做二進制數據。學習

ArrayBuffer

首先,咱們要介紹下在JavaScript中用來存儲二進制數據的ArrayBufferui

ArrayBuffer 對象用來表示通用的、固定長度的原始二進制數據緩衝區。spa

MDN的文檔中,咱們可以看到ArrayBuffer的介紹。它是在JavaScript中用來進行二進制數據存儲的一種數據對象。

下面咱們經過一個示例來簡單介紹下ArrayBuffer相關操做。

const buffer = new ArrayBuffer(8);

buffer.byteLength; // 結果爲8
複製代碼

上面的示例經過建立一個長度爲8Byte的二進制數據緩衝區。緩衝區只是一個數據存儲的空間,如何對這個存儲空間進行讀取,徹底取決於使用者。例如:8個字節能夠當成是2個Int類型的數據,也能夠是一個Long類型的數據,或者4個Short型的數據。

DataView

看完了存儲數據的ArrayBuffer,咱們來看下數據讀寫的DataView

DataView 視圖是一個能夠從 ArrayBuffer 對象中讀寫多種數值類型的底層接口,在讀寫時不用考慮平臺字節序問題。

這個是在MDN中關於DataView的介紹。DataView提供了大量的API接口來進行數據的讀和寫操做,咱們在後三章將會舉例進行說明。可是,首先咱們得先看下說明中提到的字節序問題。

字節序

在現有的計算機體系中,有兩種字節序:

  • 大端字節序:高位在前,低位在後。符合人類閱讀習慣。
  • 小端字節序:低位在前,高位在後。符合計算機讀取習慣。

上面所說的順序均是針對多字節對象而言,如Int類型,Long類型。以Int類型數據0x1234爲例,若是是大端字節序,那麼數據從人類對數值的一般寫法上來看就是0x1234;若是是小端字節序,那麼從人類對數值的一般寫法上來看,應該寫成0x3412

對於單字節對象如Byte類型數據而言,沒有字節序一說。

在不一樣的平臺中,可能使用不一樣的字節序,這就是所謂的字節序問題。DataView所謂的在讀寫時不須要考慮平臺字節序問題是指:同時使用DataView進行寫入和讀取的數據保持一致。

JavaScript中的數字數據如何轉換爲二進制數據

對ArrayBuffer和DataView有了一個大概的瞭解,下面讓咱們來看下它是如何進行二進制數據操做的。

本章,我以Short類型和Int類型爲例,介紹下相關操做步驟。

let buffer = new ArrayBuffer(6); // 初始化6個Byte的二進制數據緩衝區
let dataView = new DataView(buffer);

dataView.setInt16(0, 3); // 從第0個Byte位置開始,放置一個數字爲3的Short類型數據(佔2 Byte)
dataView.setInt32(2, 15); // 從第2個Byte位置開始,放置一個數字爲15的Short類型數據(佔4 Byte)
複製代碼

經過上面的示例,咱們一共初始化了6個Byte的存儲空間,使用1個Short類型(佔2 Byte)和一個Int類型(佔4 Byte)的數據進行填充。

DataView還提供了許多的API接口來進行其餘數據類型的處理,如無符號型,浮點數等。他們的使用方法和上面介紹的API相同,咱們在這裏就不一一進行介紹了,但願瞭解更多API接口的讀者能夠查看MDN文檔

JavaScript中如何表示Long類型而且如何將其轉換爲二進制數據

經過DataView提供的API接口,咱們知道了如何處理Short類型、Int類型、Float類型和Double類型。那麼,若是是對於Long類型這種原生API中沒有提供處理函數的數據類型,咱們應該如何處理呢?

首先,咱們須要理解Long數據類型的結構,它是由一個高位的4個Byte和低位的4個Byte組成的數據類型。由於Long類型表示的範圍比Number類型大,因此咱們在JavaScript中是使用了兩個Number類型(即Int類型)的對象來表示Long類型數據,相關的具體細節能夠見我以前的博客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); // 採用大端字節序放置
dataView.setInt32(4, long.low);
複製代碼

經過上面的示例,咱們將一個Long類型的數據拆分紅了兩個Int類型的數據,按照大端字節序放入到了ArrayBuffer中。同理,若是是想按照小端字節序放置,只須要將數據進行部分處理後再放入便可,在此我就不過多介紹了。

如何將二進制數據中轉換爲JavaScript中的數據類型

當你知道了如何將數據轉換爲ArrayBuffer中存儲的二進制數據後,就可以簡單推測出如何進行反向操做——將數據從ArrayBuffer中讀取出來,再轉換成JavaScript中經常使用數據類型。

import Long from 'long';

let buffer = new ArrayBuffer(14); // 初始化14個Byte的二進制數據緩衝區
let dataView = new DataView(buffer);
let long = Long.fromString('123');


// 數據寫入過程

dataView.setInt16(0, 3); // 從第0個Byte位置開始,放置一個數字爲3的Short類型數據(佔2 Byte)
dataView.setInt32(2, 15); // 從第2個Byte位置開始,放置一個數字爲15的Short類型數據(佔4 Byte)

dataView.setInt32(6, long.high); // 採用大端字節序放置
dataView.setInt32(10, long.low);

// 數據讀取過程

let shortNumber = dataView.getInt16(0);
let intNumber = dataView.getInt32(2);

let longNumber = Long.fromBits(dataView.getInt32(10), dataView.getInt32(6)); // 根據大端字節序讀取,該構造函數入參依次爲:低16位,高16位
複製代碼

經過上面的示例,咱們將一串二進制數據轉換成爲了JavaScript中通用的數據類型。

總結

經過使用ArrayBuffer和DataView,咱們可以快速的將數字數據從二進制轉換爲JavaScript經常使用數據類型如Int、Short等;同時,咱們也能夠將這些數據類型轉換爲二進制數據。有了這些基礎知識,咱們就可以理解在以後的博客中講到的關於使用WebSocket進行二進制數據傳遞的過程和處理邏輯。

下一篇博客咱們將介紹String類型相關的二進制處理與轉換操做,有興趣的同窗能夠關注留意下相關內容。

部分參考資料

阮一峯老師關於字節序的介紹

相關文章
相關標籤/搜索