JavsScript 使用Buffer操作二進制數據

目錄

TypedArrays

Buffer

WebWorker

注意事項



二進制數據和文本數據是我們常見的兩種格式數據。而在某些應用場景,則需要我們使用JavaScript去操作讀寫二進制格式文件,比如WebSocks獲取原始數據、操作音視頻文件、獲取商業軟件格式的數據等。儘管JavaScript是一門動態語言(弱類型),不擅長於處理二進制數據,但是我們可以使用JavaScript的類型化數組 TypedArrays操作二進制數據。

TypedArrays

JavaScript的類型化數組(TypedArrays)提供了一個更加高效的機制來訪問和處理二進制數據。以下是MDN官網對TypedArrays的介紹:

一個TypedArray 對象描述一個底層的二進制數據緩存區的一個類似數組(array-like)視圖。事實上,沒有名爲 TypedArray的全局對象,也沒有一個名爲的 TypedArray構造函數。相反,有許多不同的全局對象,下面會列出這些針對特定元素類型的類型化數組的構造函數:

// create a TypedArray with a size in bytes
const typedArray1 = new Int8Array(8);
typedArray1[0] = 32;

const typedArray2 = new Int8Array(typedArray1);
typedArray2[1] = 42;

console.log(typedArray1);
// expected output: Int8Array [32, 0, 0, 0, 0, 0, 0, 0]

console.log(typedArray2);
// expected output: Int8Array [32, 42, 0, 0, 0, 0, 0, 0]

爲了達到最大的靈活性和高效性,JavaScript的TypedArray分爲兩個部分:緩衝區和視圖。

緩衝區由ArrayBuffer實現,一個緩衝區是一個代表某個數據塊的對象。它沒有格式,而且沒有提供一個機制來訪問或操縱其中的內容。爲了存取緩衝區中 的內容,你需要創建一個視圖。視圖提供了一個環境(context),包括數據類型、起始偏移量以及元素數量。它把數據轉化爲實際上的類型化數組。視圖由 ArrayBufferView和它的一些子類實現。

從上述的描述可以看出,TypedArrays彌補了弱類型的JavaScript的缺陷。在學習TypedArrays之前,必須先要了解計算機的存儲數據各種基本類型,int, uint(無符號整形),float....。TypedArrays向我們提供多種類型的視圖實例:

  • Int8Array(); 
  • Uint8Array();
  • Uint8ClampedArray();
  • Int16Array();
  • Uint16Array();
  • Int32Array();
  • Uint32Array();
  • Float32Array();
  • Float64Array();

Int8Array是指,數組中的每一項都是一個佔8位(1字節)的整型數據。在處理二進制數據,還要考慮二進制的存儲是按照小端法還是大端法。後面在介紹Buffer類會提及。

附上TypedArrays 的官網鏈接:MDN document

Buffer

MDN官網上沒有找到Buffer類的介紹,但在Node.js的官網上有詳細的介紹Buffer的使用和實例,附上鍊接:Buffer文檔

我在處理二進制數據時,經常把ArrayBuffer直接實例化爲Buffer類去操作二進制數據流,因爲Buffer提供了很多很方便的方法讓我們去解析字節數據。包括根據字符編碼從字節碼解析出中文或者從中文解析除特定編碼的二進制,開闢內存空間,讀取不同端序的字節數據等等。

// Creates a zero-filled Buffer of length 10.
const buf1 = Buffer.alloc(10);

// Creates a Buffer of length 10, filled with 0x1.
const buf2 = Buffer.alloc(10, 1);

// Creates an uninitialized buffer of length 10.
// This is faster than calling Buffer.alloc() but the returned
// Buffer instance might contain old data that needs to be
// overwritten using either fill() or write().
const buf3 = Buffer.allocUnsafe(10);

// Creates a Buffer containing [0x1, 0x2, 0x3].
const buf4 = Buffer.from([1, 2, 3]);

// Creates a Buffer containing UTF-8 bytes [0x74, 0xc3, 0xa9, 0x73, 0x74].
const buf5 = Buffer.from('tést');

// Creates a Buffer containing Latin-1 bytes [0x74, 0xe9, 0x73, 0x74].
const buf6 = Buffer.from('tést', 'latin1');

WebWorker

Web Worker 的作用,就是爲 JavaScript 創造多線程環境,允許主線程創建 Worker 線程,將一些任務分配給後者運行。在主線程運行的同時,Worker 線程在後臺運行,兩者互不干擾。等到 Worker 線程完成計算任務,再把結果返回給主線程。這樣的好處是,一些計算密集型或高延遲的任務,被 Worker 線程負擔了,主線程(通常負責 UI 交互)就會很流暢,不會被阻塞或拖慢。

Worker 線程一旦新建成功,就會始終運行,不會被主線程上的活動(比如用戶點擊按鈕、提交表單)打斷。這樣有利於隨時響應主線程的通信。但是,這也造成了 Worker 比較耗費資源,不應該過度使用,而且一旦使用完畢,就應該關閉。

另外,Worker 線程所在的全局對象,與主線程不一樣,無法讀取主線程所在網頁的 DOM 對象,也無法使用documentwindowparent這些對象

從上述簡單的介紹,可以看出,WebWorker適合處理與DOM 對象無關的計算程序。因此,在處理二進制數據時可以使用Web Worker去創建一個新的Worker 線程去運行處理程序,從而提高運算時間,避免與UI交互產生衝突。

注意事項

在實際的讀取二進制的過程中,我們通常都需要讀取特定編碼的中文字符。此時,我們需要根據設計好的中文編碼規則去解析二進制。例如GBK的中文編碼規則是每個漢字使用雙字節表示,而UTF-8是使用可變長字節去存儲字符,英文使用一個字節,中文使用三個字節。

因此,在讀取中文時,必須清楚知道二進制流中中文字符的編碼,才能解析得到正確的內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章