js的string变量存储字符串使用的是unicode编码,要保存时必须选择其他编码后进行传输,比如转成utf-8,utf-32等。存储到数据库中为utf-8编码,读取出来如何转换成正确的字符串就成了问题。现在给出解决方案,可以正确支持中文、emoji表情、英文混合的字符串编码互转。

/**
* 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 ){ //
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的字节字符,占两个unicode字符。使用String.fromCharCode也可以实现,需要进行两次fromCharCode,没有fromPointCode方便。下面展示了utf-8的4字节转换为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已经占据10位
unicode = unicode - parseInt('1000000',2) //加上utf-16高char的标识符
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的标识符
unicode = 0xDC00 + unicode;
console.log(unicode);
unicodeStr+= String.fromCharCode(unicode);
pos += 4;

参考链接:

https://www.oschina.net/question/1046342_2199669

https://blog.csdn.net/weixin_37925993/article/details/79522812

https://blog.csdn.net/guxiaonuan/article/details/78678043

js实现unicode码字符串与utf8字节数据互转的更多相关文章

  1. JAVA js的escape函数、解析用js encodeURI编码的字符串、utf8转gb2312的函数

    在使用webView时,如果url中参数有中文的话,拦截到的字符串就会类似这样的:http://api.letstar.cn/zq/news.html?id=20&cupName=%E6%B5 ...

  2. JS将unicode码转中文方法

    原理,将unicode的 \u 先转为 %u,然后使用unescape方法转换为中文. ? 1 2 3 4 <script type="text/javascript"> ...

  3. JS 时间转换函数 字符串时间转换毫秒(互转)

    字符串转化为日期 let util = function(){ Date.prototype.Format = function(fmt) { var o = { "M+" : t ...

  4. JS之汉字与Unicode码的相互转化

    有时候,我们在给后端传递变量的的值中有汉字,可能由于编码的原因,传递到后端后变为乱码了.所以有时候为了省事或者其它特殊要求的时候,会把传递的汉字转换成Unicode编码后再进行传递. 当然汉字转换成u ...

  5. JS计算字符串所占字节数

    最近项目有个需求要用js计算一串字符串写入到localStorage里所占的内存,众所周知的,js是使用Unicode编码的.而Unicode的实现有N种,其中用的最多的就是UTF-8和UTF-16. ...

  6. ASCII码、ISO8859-1、Unicode、GBK和UTF-8 的区别

    为什么需要编码? 计算机中最小的存储单位是字节(byte),一个字节所能表示的字符数又有限,1byte=8bit,一个字节最多也只能表示255个字符,而世界上的语种又多,都有各种不同的字符,无法用一个 ...

  7. 【javascript基础】JS计算字符串所占字节数

    废话不说,直接正题吧. 最近项目有个需求要用js计算一串字符串写入到localStorage里所占的内存,众所周知的,js是使用Unicode编码的.而Unicode的实现有N种,其中用的最多的就是U ...

  8. 汉字编码(【Unicode】 【UTF-8】 【Unicode与UTF-8之间的转换】 【汉字 Unicode 编码范围】【中文标点Unicode码】【GBK编码】【批量获取汉字UNICODE码】)

    Unicode与UTF-8互转(C语言实现):http://blog.csdn.net/tge7618291/article/details/7599902 汉字 Unicode 编码范围:http: ...

  9. [IOS微信] Unicode码 转化为字符串

    最近在研究IOS手机备份的数据,里面的微信数据中,每一个微信账号对应一个文件:mmsetting.archive 用来保存此账号的详细信息. 该文件是一个加强版的plist文件(此文件使用的是plis ...

随机推荐

  1. django系列9--django中的组件(form表单)

    modelform整体 from django import forms from app01 import models import hashlib from django.core.except ...

  2. python del 方法的使用

    在Python 的自带函数中 del 函数是一个非常特殊但是又非常使用的函数 my_list = [1,2,3] my_dict = {"name":"lowman&qu ...

  3. jzoj5806

    我們發現,如果有奇環顯然無解,因為我們每一次合併一個奇環,一定會產生一個偶環和一個更小的奇環,最終會形成一個三元環而無法合併 所以,這個圖需要是一個二分圖,需要進行二染色 然後把這個圖所有的偶環找出來 ...

  4. Nexus3.6 window版私服搭建 安装、配置教程

    1.本地环境配置(Nexus3.6支持jdk版本1.6.1.7.1.8) 1.1.官网下载地址:https://www.sonatype.com/download-oss-sonatype       ...

  5. maven 服务器搭建 -- nexus

    参考文档 http://blog.sina.com.cn/s/blog_5745d6cb0100hasa.html 首先下载nexus webapp,可以使用wget来下载: Java代码 wget  ...

  6. eclipse 使用prolog编程

    第一步:在电脑上安装swi-prolog 相应环境下载地址http://www.swi-prolog.org/download/stable 第二步: eclipse-help-install new ...

  7. python实现百度地图API获取某地址的经纬度

    申请百度API 1.打开网页 http://lbsyun.baidu.com/index.php?title=首页 选择功能与服务中的地图,点击左边的获取密匙,然后按照要求申请即可,需要手机和百度账号 ...

  8. 剑指offer四十九之把字符串转换成整数

    一.题目 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 二.思路 详见代码. 三.代码 public class Solution { ...

  9. 解决ssh/scp报错:Someone could be eavesdropping on you right now (man-in-the-middle attack)!

    主要现象:ssh/scp 失败,host key verification failed. # scp /home/iso/********.iso root@192.168.1.***:/home/ ...

  10. CharacterRangeTable

    转载:https://github.com/jacoco/jacoco/wiki/CharacterRangeTable This page discusses a not yet available ...