js實現(xiàn)unicode碼字符串與utf8字節(jié)數(shù)據(jù)互轉(zhuǎn)詳解
js的string變量存儲字符串使用的是unicode編碼,要保存時必須選擇其他編碼后進(jìn)行傳輸,比如轉(zhuǎn)成utf-8,utf-32等。存儲到數(shù)據(jù)庫中為utf-8編碼,讀取出來如何轉(zhuǎn)換成正確的字符串就成了問題?,F(xiàn)在給出解決方案,可以正確支持中文、emoji表情、英文混合的字符串編碼互轉(zhuǎn)。
/**
* Created by hdwang on 2019/1/28.
*/
var convertUtf8 = (function() {
/**
* unicode string to utf-8
* @param text 字符串
* @returns {*} utf-8編碼
*/
function toBytes(text) {
var result = [], i = 0;
text = encodeURI(text);
while (i < text.length) {
var c = text.charCodeAt(i++);
// if it is a % sign, encode the following 2 bytes as a hex value
if (c === 37) {
result.push(parseInt(text.substr(i, 2), 16))
i += 2;
// otherwise, just the actual byte
} else {
result.push(c)
}
}
return coerceArray(result);
}
/**
* utf8 byte to unicode string
* @param utf8Bytes
* @returns {string}
*/
function utf8ByteToUnicodeStr(utf8Bytes){
var unicodeStr ="";
for (var pos = 0; pos < utf8Bytes.length;){
var flag= utf8Bytes[pos];
var unicode = 0 ;
if ((flag >>>7) === 0 ) {
unicodeStr+= String.fromCharCode(utf8Bytes[pos]);
pos += 1;
} else if ((flag &0xFC) === 0xFC ){
unicode = (utf8Bytes[pos] & 0x3) << 30;
unicode |= (utf8Bytes[pos+1] & 0x3F) << 24;
unicode |= (utf8Bytes[pos+2] & 0x3F) << 18;
unicode |= (utf8Bytes[pos+3] & 0x3F) << 12;
unicode |= (utf8Bytes[pos+4] & 0x3F) << 6;
unicode |= (utf8Bytes[pos+5] & 0x3F);
unicodeStr+= String.fromCodePoint(unicode) ;
pos += 6;
}else if ((flag &0xF8) === 0xF8 ){
unicode = (utf8Bytes[pos] & 0x7) << 24;
unicode |= (utf8Bytes[pos+1] & 0x3F) << 18;
unicode |= (utf8Bytes[pos+2] & 0x3F) << 12;
unicode |= (utf8Bytes[pos+3] & 0x3F) << 6;
unicode |= (utf8Bytes[pos+4] & 0x3F);
unicodeStr+= String.fromCodePoint(unicode) ;
pos += 5;
} else if ((flag &0xF0) === 0xF0 ){
unicode = (utf8Bytes[pos] & 0xF) << 18;
unicode |= (utf8Bytes[pos+1] & 0x3F) << 12;
unicode |= (utf8Bytes[pos+2] & 0x3F) << 6;
unicode |= (utf8Bytes[pos+3] & 0x3F);
unicodeStr+= String.fromCodePoint(unicode) ;
pos += 4;
} else if ((flag &0xE0) === 0xE0 ){
unicode = (utf8Bytes[pos] & 0x1F) << 12;;
unicode |= (utf8Bytes[pos+1] & 0x3F) << 6;
unicode |= (utf8Bytes[pos+2] & 0x3F);
unicodeStr+= String.fromCharCode(unicode) ;
pos += 3;
} else if ((flag &0xC0) === 0xC0 ){ //110
unicode = (utf8Bytes[pos] & 0x3F) << 6;
unicode |= (utf8Bytes[pos+1] & 0x3F);
unicodeStr+= String.fromCharCode(unicode) ;
pos += 2;
} else{
unicodeStr+= String.fromCharCode(utf8Bytes[pos]);
pos += 1;
}
}
return unicodeStr;
}
function checkInt(value) {
return (parseInt(value) === value);
}
function checkInts(arrayish) {
if (!checkInt(arrayish.length)) { return false; }
for (var i = 0; i < arrayish.length; i++) {
if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) {
return false;
}
}
return true;
}
function coerceArray(arg, copy) {
// ArrayBuffer view
if (arg.buffer && arg.name === 'Uint8Array') {
if (copy) {
if (arg.slice) {
arg = arg.slice();
} else {
arg = Array.prototype.slice.call(arg);
}
}
return arg;
}
// It's an array; check it is a valid representation of a byte
if (Array.isArray(arg)) {
if (!checkInts(arg)) {
throw new Error('Array contains invalid value: ' + arg);
}
return new Uint8Array(arg);
}
// Something else, but behaves like an array (maybe a Buffer? Arguments?)
if (checkInt(arg.length) && checkInts(arg)) {
return new Uint8Array(arg);
}
throw new Error('unsupported array-like object');
}
return {
toBytes: toBytes,
fromBytes: utf8ByteToUnicodeStr
}
})()
針對emoji的字節(jié)字符,占兩個unicode字符。使用String.fromCharCode也可以實現(xiàn),需要進(jìn)行兩次fromCharCode,沒有fromPointCode方便。下面展示了utf-8的4字節(jié)轉(zhuǎn)換為unicode(utf-16)的過程。
//高char10位[一個unicode字符] (2+6+2=10)
unicode = ((utf8Bytes[pos] & 0x3)) << 8 |((utf8Bytes[pos+1] & 0x3f) << 2) |((utf8Bytes[pos+2] >> 4) & 0x03);
//減去1F600中的1,這里減去6個0即可,低位char已經(jīng)占據(jù)10位
unicode = unicode - parseInt('1000000',2)
//加上utf-16高char的標(biāo)識符
unicode = 0xD800 + unicode;
console.log(unicode);
unicodeStr += String.fromCharCode(unicode);
//低char10位[一個unicode字符](4+6)
unicode = ((utf8Bytes[pos+2] & 0x0F) << 6) | (utf8Bytes[pos+3] & 0x3F);
//加上utf-16低char的標(biāo)識符
unicode = 0xDC00 + unicode;
console.log(unicode);
unicodeStr+= String.fromCharCode(unicode);
pos += 4;
以上所述是小編給大家介紹的js實現(xiàn)unicode碼字符串與utf8字節(jié)數(shù)據(jù)互轉(zhuǎn)詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
微信公眾號開發(fā) 自定義菜單跳轉(zhuǎn)頁面并獲取用戶信息實例詳解
這篇文章主要介紹了微信公眾號開發(fā) 自定義菜單跳轉(zhuǎn)頁面并獲取用戶信息實例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12
關(guān)于JavaScript限制字?jǐn)?shù)的輸入框的那些事
這篇文章主要介紹了關(guān)于JavaScript限制字?jǐn)?shù)的輸入框在項目過程中容易遇到的各種坑的匯總,非常的詳細(xì),有需要的小伙伴可以參考下2016-08-08
javascript創(chuàng)建對象、對象繼承的實用方式詳解
JavaScript中的對象是基于原型的。原型是對象的基礎(chǔ),它定義并實現(xiàn)了一個新對象所必須包含的成員列表,并被所有同類對象實例所共享。與其他語言中類的概念相比,原型更像是類的靜態(tài)成員。本文著重給大家介紹javascript創(chuàng)建對象、對象繼承的實用方式2016-03-03
深入理解JavaScript系列(42):設(shè)計模式之原型模式詳解
這篇文章主要介紹了深入理解JavaScript系列(42):設(shè)計模式之原型模式詳解,原型模式(prototype)是指用原型實例指向創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象,需要的朋友可以參考下2015-03-03

