上一篇博客咱們說到了如何進行數字類型(如Short、Int、Long類型)如何在JavaScript中進行二進制轉換,若是感興趣的能夠能夠閱讀本系列第二篇博客——WebSocket系列之JavaScript中數字數據如何轉換爲二進制數據。此次,咱們來講下string類型的數據如何進行處理。 本文是WebSocket系列的第三篇,主要介紹string數據與二進制數據之間的轉換方法,具體的內容以下:javascript
string這個類型,對於熟悉JavaScript的同窗應該都不陌生,它是屬於JavaScript中基礎數據類型的一種。不過,咱們今天要先介紹下DOMString
。java
DOMString 是一個UTF-16字符串。因爲JavaScript已經使用了這樣的字符串,因此DOMString 直接映射到 一個String。將null傳遞給接受DOMString的方法或參數時一般會把其轉換成爲「null」。git
在WebSocket中進行string類型數據傳輸時,使用的其實也是DOMString
。不過,根據MDN中對DOMString
的介紹咱們能夠了解到,大部分平常使用場景中,咱們能夠認爲DOMString
就是一個string類型。因此,咱們只須要了解此類型,使用時仍然當成string類型處理便可。github
既然上面提到了UTF-16,那麼咱們就來簡單介紹下UTF-16,以及後端經常使用的UTF-8這兩種編碼方式。 爲何須要介紹編碼類型呢?由於咱們在與後端進行字符串數據傳遞時,可能使用的編碼方式不一樣,這樣就會致使雙方獲得不一樣的數據。所以,咱們在進行string的二進制數據通訊時,不只僅須要將字符串轉換成二進制,還須要協商一致的string編碼。後端
UTF-16 (16-bit Unicode Transformation Format) 是Unicode字符編碼五層次模型的第三層:字符編碼表(Character Encoding Form,也稱爲"storage format")的一種實現方式。即把Unicode字符集的抽象碼位映射爲16位長的整數(即碼元)的序列,用於數據存儲或傳遞。 Unicode字符的碼位,須要1個或者2個16位長的碼元來表示,所以這是一個變長表示。數組
UTF-16是JavaScript中的string編碼類型。函數
UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,也是一種前綴碼。它能夠用來表示Unicode標準中的任何字元,且其編碼中的第一個字節仍與ASCII兼容,這使得原來處理ASCII字元的軟件無須或只須作少部分修改,便可繼續使用。UTF-8使用一至四個字節爲每一個字符編碼(2003年11月從新規範)。post
UTF-8是不少語言使用的通用編碼類型,在後端應用中很是常見。ui
在Github上有轉換庫GitHub - dcodeIO/utfx: A compact library to encode, decode and convert UTF8 / UTF16 in JavaScript.,經過這個庫,能夠將字符串在UTF-8編碼和UTF-16編碼中進行轉換。該庫的具體原理和內容以及兩種編碼方式的詳細內容說明將會在以後的博客中進行講解。咱們下面簡單的介紹下它是使用方式:this
import utfx from './util/utfx';
let str = 'abcdefg';
let result = [];
function stringSource(s) {
let i = 0;
return function () {
return i < s.length ? s.charCodeAt(i++) : null;
};
}
utfx.encodeUTF16toUTF8(stringSource(str), function (b) {
result.push(b);
}.bind(this));
複製代碼
同理,該類庫提供了其餘的方法:
decodeUTF8toUTF16
,將UTF-8的string數據轉換爲UTF-16的string數據。calculateUTF16asUTF8
,計算UTF-16編碼的string類型類型轉換爲UTF-8後所佔Byte長度。 這兩個方法咱們在以後的章節中也會用到。瞭解了JavaScript中string類型的編碼和在UTF-8和UTF-16之間轉換編碼的方式,下面咱們來看下如何將string類型轉換爲二進制數據。 首先,咱們假定與後端交互時使用的編碼方式爲UTF-8,這樣可以知足更多的使用場景。若是仍然使用UTF-16的話,則直接忽略轉換編碼的邏輯便可。 簡單介紹下實現思路:咱們獲得一個須要轉換的字符串後,先知道其長度後,初始化ArrayBuffer中相關參數,將數據放入ArrayBuffer中便可。咱們將上面的示例稍做改動:
import utfx from './util/utfx';
function stringSource(s) {
var i = 0;
return function () {
return i < s.length ? s.charCodeAt(i++) : null;
};
}
let str = 'abcdefg';
let strCodes = stringSource(str);
let length = utfx.calculateUTF16asUTF8(strCodes)[1];
let buffer = new ArrayBuffer(length + 4); // 初始化長度爲UTF8編碼後字符串長度+4個Byte的二進制緩衝區
let view = new DataView(buffer);
let offset = 4;
view.setUint32(0, length); // 將長度放置在字符串的頭部
utfx.encodeUTF16toUTF8(stringSource(str), function (b) {
view.setUint8(offset++, b);
}.bind(this));
複製代碼
經過上面的示例,咱們就已經將一個二進制數據根據UTF-8編碼後放入了ArrayBuffer中,同時,將其長度做爲一個Unsigned Int類型存儲在了二進制頭部4個Byte的位置。
知道了如何將string類型轉換爲二進制數據,下面咱們看下如何將整個數據從二進制中讀取,轉換回string類型。 根據上面轉換爲二進制的過程,咱們不難想到相關的二進制轉string類型方法。具體示例以下:
import utfx from './util/utfx';
let str = 'abcdefg';
function stringSource(s) {
var i = 0;
return function () {
return i < s.length ? s.charCodeAt(i++) : null;
};
}
let strCodes = stringSource(str);
let length = utfx.calculateUTF16asUTF8(strCodes)[1];
let buffer = new ArrayBuffer(length + 4); // 初始化長度爲UTF8編碼後字符串長度+4個Byte的二進制緩衝區
let view = new DataView(buffer);
let offset = 4;
// 字符串轉換二進制過程
view.setUint32(0, length); // 將長度放置在字符串的
utfx.encodeUTF16toUTF8(stringSource(str), function (b) {
view.setUint8(offset++, b);
}.bind(this));
// 二進制轉換字符串過程
let Strlength = view.getUint32(0);
offset = 4;
let result = []; // Unicode編碼字符
let end = offset + Strlength;
utfx.decodeUTF8toUTF16(function () {
return offset < end ? view.getUint8(offset++) : null; // 返回null時會退出此轉換函數
}.bind(this), (char) => {
console.log(char)
result.push(char);
});
let strResult = result.reduce((prev, next)=>{
return prev + String.fromCharCode(next);
}, '');
複製代碼
經過上面的示例咱們能夠知道,咱們只須要在前面4個Byte中將字符串長度讀取出來,而後再從第4個Byte(從0開始算)的位置開始讀取指定長度的字符串字符編碼便可。最後,咱們獲得了一個Unicode碼數組,只須要fromCharCode
方法便可將其轉換爲字符串。
經過使用ArrayBuffer和DataView,咱們可以在string數據和二進制數據中進行互相轉換。 有了string類型轉換的相關基礎,讀者就可以在以後的WebSocket進行二進制數據傳遞時理解相關的內容和處理邏輯。 下一篇WebSocket系列相關的博客,將會介紹如何經過WebSocket來向後端傳遞二進制數據,以及如何處理經過WebSocket收到的二進制數據。有興趣的同窗能夠繼續關注。