摘要:總結(jié)通過(guò)使用和,我們能夠在數(shù)據(jù)和二進(jìn)制數(shù)據(jù)中進(jìn)行互相轉(zhuǎn)換。下一篇系列相關(guān)的博客,將會(huì)介紹如何通過(guò)來(lái)向后端傳遞二進(jìn)制數(shù)據(jù),以及如何處理通過(guò)收到的二進(jìn)制數(shù)據(jù)。
概述
上一篇博客我們說(shuō)到了如何進(jìn)行數(shù)字類型(如Short、Int、Long類型)如何在JavaScript中進(jìn)行二進(jìn)制轉(zhuǎn)換,如果感興趣的可以可以閱讀本系列第二篇博客——WebSocket系列之JavaScript中數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)。這次,我們來(lái)說(shuō)下string類型的數(shù)據(jù)如何進(jìn)行處理。
本文是WebSocket系列的第三篇,主要介紹string數(shù)據(jù)與二進(jìn)制數(shù)據(jù)之間的轉(zhuǎn)換方法,具體的內(nèi)容如下:
JavaScript中string類型基礎(chǔ)知識(shí)
JavaScript如何將string類型轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)
JavaScript如何將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為string類型
本文與WebSocket并無(wú)太強(qiáng)關(guān)聯(lián),不過(guò)作為在WebSocket中傳遞二進(jìn)制數(shù)據(jù)的基礎(chǔ)知識(shí)儲(chǔ)備,因此放入了此系列當(dāng)中。
如果讀者對(duì)WebSocket并不了解,或者說(shuō)不明白它的使用場(chǎng)景和細(xì)節(jié),可以閱讀我的本系列的第一篇博客——WebSocket系列之基礎(chǔ)知識(shí)入門篇。
string這個(gè)類型,對(duì)于熟悉JavaScript的同學(xué)應(yīng)該都不陌生,它是屬于JavaScript中基礎(chǔ)數(shù)據(jù)類型的一種。不過(guò),我們今天要先介紹下DOMString。
DOMString 是一個(gè)UTF-16字符串。由于JavaScript已經(jīng)使用了這樣的字符串,所以DOMString 直接映射到 一個(gè)String。將null傳遞給接受DOMString的方法或參數(shù)時(shí)通常會(huì)把其轉(zhuǎn)換成為“null”。
在WebSocket中進(jìn)行string類型數(shù)據(jù)傳輸時(shí),使用的其實(shí)也是DOMString。不過(guò),根據(jù)MDN中對(duì)DOMString的介紹我們可以了解到,大部分日常使用場(chǎng)景中,我們可以認(rèn)為DOMString就是一個(gè)string類型。所以,我們只需要了解此類型,使用時(shí)仍然當(dāng)成string類型處理即可。
編碼既然上面提到了UTF-16,那么我們就來(lái)簡(jiǎn)單介紹下UTF-16,以及后端常用的UTF-8這兩種編碼方式。
為什么需要介紹編碼類型呢?因?yàn)槲覀冊(cè)谂c后端進(jìn)行字符串?dāng)?shù)據(jù)傳遞時(shí),可能使用的編碼方式不同,這樣就會(huì)導(dǎo)致雙方得到不同的數(shù)據(jù)。因此,我們?cè)谶M(jìn)行string的二進(jìn)制數(shù)據(jù)通信時(shí),不僅僅需要將字符串轉(zhuǎn)換成二進(jìn)制,還需要協(xié)商一致的string編碼。
UTF-16 (16-bit Unicode Transformation Format) 是Unicode字符編碼五層次模型的第三層:字符編碼表(Character Encoding Form,也稱為"storage format")的一種實(shí)現(xiàn)方式。即把Unicode字符集的抽象碼位映射為16位長(zhǎng)的整數(shù)(即碼元)的序列,用于數(shù)據(jù)存儲(chǔ)或傳遞。
Unicode字符的碼位,需要1個(gè)或者2個(gè)16位長(zhǎng)的碼元來(lái)表示,因此這是一個(gè)變長(zhǎng)表示。
UTF-16是JavaScript中的string編碼類型。
UTF-8UTF-8(8-bit Unicode Transformation Format)是一種針對(duì)Unicode的可變長(zhǎng)度字符編碼,也是一種前綴碼。它可以用來(lái)表示Unicode標(biāo)準(zhǔn)中的任何字元,且其編碼中的第一個(gè)字節(jié)仍與ASCII兼容,這使得原來(lái)處理ASCII字元的軟件無(wú)須或只須做少部分修改,即可繼續(xù)使用。UTF-8使用一至四個(gè)字節(jié)為每個(gè)字符編碼(2003年11月重新規(guī)范)。
UTF-8是很多語(yǔ)言使用的通用編碼類型,在后端應(yīng)用中非常常見(jiàn)。
JavaScript中UTF16和UTF-8如何進(jìn)行編碼轉(zhuǎn)換在Github上有轉(zhuǎn)換庫(kù)GitHub - dcodeIO/utfx: A compact library to encode, decode and convert UTF8 / UTF16 in JavaScript.,通過(guò)這個(gè)庫(kù),可以將字符串在UTF-8編碼和UTF-16編碼中進(jìn)行轉(zhuǎn)換。該庫(kù)的具體原理和內(nèi)容以及兩種編碼方式的詳細(xì)內(nèi)容說(shuō)明將會(huì)在之后的博客中進(jìn)行講解。我們下面簡(jiǎn)單的介紹下它是使用方式:
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));
同理,該類庫(kù)提供了其他的方法:
decodeUTF8toUTF16,將UTF-8的string數(shù)據(jù)轉(zhuǎn)換為UTF-16的string數(shù)據(jù)。
calculateUTF16asUTF8,計(jì)算UTF-16編碼的string類型類型轉(zhuǎn)換為UTF-8后所占Byte長(zhǎng)度。
這兩個(gè)方法我們?cè)谥蟮恼鹿?jié)中也會(huì)用到。
了解了JavaScript中string類型的編碼和在UTF-8和UTF-16之間轉(zhuǎn)換編碼的方式,下面我們來(lái)看下如何將string類型轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)。
首先,我們假定與后端交互時(shí)使用的編碼方式為UTF-8,這樣能夠滿足更多的使用場(chǎng)景。如果仍然使用UTF-16的話,則直接忽略轉(zhuǎn)換編碼的邏輯即可。
簡(jiǎn)單介紹下實(shí)現(xiàn)思路:我們得到一個(gè)需要轉(zhuǎn)換的字符串后,先知道其長(zhǎng)度后,初始化ArrayBuffer中相關(guān)參數(shù),將數(shù)據(jù)放入ArrayBuffer中即可。我們將上面的示例稍作改動(dòng):
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); // 初始化長(zhǎng)度為UTF8編碼后字符串長(zhǎng)度+4個(gè)Byte的二進(jìn)制緩沖區(qū) let view = new DataView(buffer); let offset = 4; view.setUint32(0, length); // 將長(zhǎng)度放置在字符串的頭部 utfx.encodeUTF16toUTF8(stringSource(str), function (b) { view.setUint8(offset++, b); }.bind(this));
通過(guò)上面的示例,我們就已經(jīng)將一個(gè)二進(jìn)制數(shù)據(jù)根據(jù)UTF-8編碼后放入了ArrayBuffer中,同時(shí),將其長(zhǎng)度作為一個(gè)Unsigned Int類型存儲(chǔ)在了二進(jìn)制頭部4個(gè)Byte的位置。
JavaScript如何將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為string類型知道了如何將string類型轉(zhuǎn)換為二進(jìn)制數(shù)據(jù),下面我們看下如何將整個(gè)數(shù)據(jù)從二進(jìn)制中讀取,轉(zhuǎn)換回string類型。
根據(jù)上面轉(zhuǎn)換為二進(jìn)制的過(guò)程,我們不難想到相關(guān)的二進(jìn)制轉(zhuǎn)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); // 初始化長(zhǎng)度為UTF8編碼后字符串長(zhǎng)度+4個(gè)Byte的二進(jìn)制緩沖區(qū) let view = new DataView(buffer); let offset = 4; // 字符串轉(zhuǎn)換二進(jìn)制過(guò)程 view.setUint32(0, length); // 將長(zhǎng)度放置在字符串的 utfx.encodeUTF16toUTF8(stringSource(str), function (b) { view.setUint8(offset++, b); }.bind(this)); // 二進(jìn)制轉(zhuǎn)換字符串過(guò)程 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時(shí)會(huì)退出此轉(zhuǎn)換函數(shù) }.bind(this), (char) => { console.log(char) result.push(char); }); let strResult = result.reduce((prev, next)=>{ return prev + String.fromCharCode(next); }, "");
通過(guò)上面的示例我們可以知道,我們只需要在前面4個(gè)Byte中將字符串長(zhǎng)度讀取出來(lái),然后再?gòu)牡?個(gè)Byte(從0開(kāi)始算)的位置開(kāi)始讀取指定長(zhǎng)度的字符串字符編碼即可。最后,我們得到了一個(gè)Unicode碼數(shù)組,只需要fromCharCode方法即可將其轉(zhuǎn)換為字符串。
總結(jié)通過(guò)使用ArrayBuffer和DataView,我們能夠在string數(shù)據(jù)和二進(jìn)制數(shù)據(jù)中進(jìn)行互相轉(zhuǎn)換。
有了string類型轉(zhuǎn)換的相關(guān)基礎(chǔ),讀者就能夠在之后的WebSocket進(jìn)行二進(jìn)制數(shù)據(jù)傳遞時(shí)理解相關(guān)的內(nèi)容和處理邏輯。
下一篇WebSocket系列相關(guān)的博客,將會(huì)介紹如何通過(guò)WebSocket來(lái)向后端傳遞二進(jìn)制數(shù)據(jù),以及如何處理通過(guò)WebSocket收到的二進(jìn)制數(shù)據(jù)。有興趣的同學(xué)可以繼續(xù)關(guān)注。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93842.html
摘要:本文作為系列的第四篇內(nèi)容,將會(huì)用一個(gè)簡(jiǎn)單的聊天應(yīng)用把整個(gè)傳輸二進(jìn)制數(shù)據(jù)類型的內(nèi)容連接起來(lái),讓用戶對(duì)整個(gè)傳輸二進(jìn)制數(shù)據(jù)的方法有個(gè)了解。如何發(fā)送二進(jìn)制數(shù)據(jù)通過(guò)如何設(shè)計(jì)一個(gè)二進(jìn)制協(xié)議一章,我們知道了如何定義傳輸?shù)亩M(jìn)制數(shù)據(jù)格式。 概述 通過(guò)前三篇博客,我們能夠了解在通過(guò)WebSocket發(fā)送數(shù)據(jù)之前,我們需要傳遞的數(shù)據(jù)是如何變成ArrayBuffer二進(jìn)制數(shù)據(jù)的;在我們收到二進(jìn)制數(shù)據(jù)之后,我...
摘要:概述本文是系列的第一篇,主要介紹相關(guān)的基礎(chǔ)協(xié)議知識(shí)和??蛻舳耸盏巾憫?yīng)后,立即發(fā)起下一次的請(qǐng)求。收到消息通過(guò)事件來(lái)接收消息。類型則需要傳遞一個(gè)對(duì)象作為參數(shù),相關(guān)的內(nèi)容也將在本系列第二篇中進(jìn)行介紹。 概述 本文是WebSocket系列的第一篇,主要介紹WebSocket相關(guān)的基礎(chǔ)協(xié)議知識(shí)和API。由于WebSocket的相關(guān)介紹在MDN中分布較亂,初學(xué)者不太容易入門,因此通過(guò)本文將相關(guān)基礎(chǔ)...
摘要:與此同時(shí),后端服務(wù)的中也有相關(guān)的長(zhǎng)連接維持時(shí)長(zhǎng)設(shè)置。如何快速的恢復(fù)連接根據(jù)上面的操作方案,我們會(huì)在網(wǎng)絡(luò)異常時(shí)斷開(kāi)連接。 概述 通過(guò)前四篇博客,相信讀者對(duì)于WebSocket的使用和數(shù)據(jù)(不論是ArrayBuffer還是String)傳輸都有了一個(gè)深刻的了解?,F(xiàn)在我們來(lái)介紹下,我在使用WebSocket時(shí),連接相關(guān)模塊遇到的一些共性問(wèn)題,以及我們?nèi)绾谓鉀Q這些問(wèn)題。 本文作為WebSock...
摘要:編碼轉(zhuǎn)換為編碼下面讓我們來(lái)看下如何將編碼的數(shù)據(jù)轉(zhuǎn)換為編碼的數(shù)據(jù)。該方法是將碼進(jìn)行編碼轉(zhuǎn)換,從而得到編碼的數(shù)據(jù)。 概述 當(dāng)你在前端需要通過(guò)二進(jìn)制數(shù)據(jù)與服務(wù)端進(jìn)行通信時(shí),你可能會(huì)遇到二進(jìn)制數(shù)據(jù)的編碼問(wèn)題。大部分服務(wù)端的字符串編碼類型都為UTF-8,而JavaScript中字符串編碼類型是UTF-16,因此,你需要一個(gè)能夠?qū)⒆址趦煞N編碼方式間進(jìn)行轉(zhuǎn)換的方法。 本文通過(guò)對(duì)utfx.js這個(gè)...
摘要:以和為例,說(shuō)明中的數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)。對(duì)象用來(lái)表示通用的固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。中的數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)對(duì)和有了一個(gè)大概的了解,下面讓我們來(lái)看下它是如何進(jìn)行二進(jìn)制數(shù)據(jù)操作的。 概述 本文主要通過(guò)對(duì)JavaScript中數(shù)字?jǐn)?shù)據(jù)與二進(jìn)制數(shù)據(jù)之間的轉(zhuǎn)換,讓讀者能夠了解在JavaScript中如何對(duì)數(shù)字類型(包括但不限于Number類型)進(jìn)行處理。 二進(jìn)制數(shù)據(jù)在日常...
閱讀 726·2023-04-25 17:54
閱讀 2986·2021-11-18 10:02
閱讀 1143·2021-09-28 09:35
閱讀 663·2021-09-22 15:18
閱讀 2867·2021-09-03 10:49
閱讀 3065·2021-08-10 09:42
閱讀 2588·2019-08-29 16:24
閱讀 1267·2019-08-29 15:08