js实现unicode码字符串与utf8字节数据互转详解


Posted in Javascript onMarch 21, 2019

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 ){ //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的字节字符,占两个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;

以上所述是小编给大家介绍的js实现unicode码字符串与utf8字节数据互转详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js面向对象编程之如何实现方法重载
Jul 02 Javascript
JavaScript eval() 函数介绍及应用示例
Jul 29 Javascript
在HTML代码中使用JavaScript代码的例子
Oct 16 Javascript
AngularJS基础学习笔记之指令
May 10 Javascript
JSON相关知识汇总
Jul 03 Javascript
jQuery实现的兼容性浮动层示例
Aug 02 Javascript
Angularjs 手写日历的实现代码(不用插件)
Oct 18 Javascript
基于jQuery实现无缝轮播与左右点击效果
May 13 jQuery
详解Vue结合后台的列表增删改案例
Aug 21 Javascript
angular4自定义组件非input元素实现ngModel双向数据绑定的方法
Dec 28 Javascript
layUI的验证码功能及校验实例
Oct 25 Javascript
如何理解Vue前后端数据交互与显示
May 10 Vue.js
详解JS取出两个数组中的不同或相同元素
Mar 20 #Javascript
详解vue中axios的使用与封装
Mar 20 #Javascript
javascript数组去重方法总结(推荐)
Mar 20 #Javascript
浅谈JavaScript面向对象--继承
Mar 20 #Javascript
小程序显示弹窗时禁止下层的内容滚动实现方法
Mar 20 #Javascript
vue踩坑记录之数组定义和赋值问题
Mar 20 #Javascript
vue实现微信二次分享以及自定义分享的示例
Mar 20 #Javascript
You might like
《超神学院》霸气归来, 天使彦上演维多利亚的秘密
2020/03/02 国漫
MYSQL环境变量设置方法
2007/01/15 PHP
最常用的8款PHP调试工具
2014/07/06 PHP
你应该知道PHP浮点数知识
2015/05/13 PHP
PHP基于PDO扩展操作mysql数据库示例
2018/12/24 PHP
PHP数据对象映射模式实例分析
2019/03/29 PHP
PHP dirname(__FILE__)原理及用法解析
2020/10/28 PHP
JavaScript constructor和instanceof,JSOO中的一对欢喜冤家
2009/05/25 Javascript
推荐11款jQuery开发的复选框和单选框美化插件
2011/08/02 Javascript
jquery实现可自动收缩的TAB网页选项卡代码
2015/09/06 Javascript
javascript实现网页端解压并查看zip文件
2015/12/15 Javascript
AngularJs Javascript MVC 框架
2016/06/20 Javascript
jQuery文字提示与图片提示效果实现方法
2016/07/04 Javascript
微信小程序实现红包雨功能
2018/07/11 Javascript
使用Vue实现图片上传的三种方式
2018/07/17 Javascript
jQuery实现的淡入淡出图片轮播效果示例
2018/08/29 jQuery
你不可不知的Vue.js列表渲染详解
2019/10/01 Javascript
Python标准库内置函数complex介绍
2014/11/25 Python
讲解Python中fileno()方法的使用
2015/05/24 Python
对numpy 数组和矩阵的乘法的进一步理解
2018/04/04 Python
使用python打印十行杨辉三角过程详解
2019/07/10 Python
利用python计算时间差(返回天数)
2019/09/07 Python
Python numpy.zero() 初始化矩阵实例
2019/11/27 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
2020/06/18 Python
python实现跨年表白神器--你值得拥有
2021/01/04 Python
可以随进度显示不同颜色的css3进度条分享
2014/04/11 HTML / CSS
秘书行业自我鉴定范文
2013/12/30 职场文书
高二政治教学反思
2014/02/01 职场文书
语文教学随笔感言
2014/02/18 职场文书
财务管理专业自荐书
2014/09/02 职场文书
教师国庆节演讲稿范文2014
2014/09/21 职场文书
患者身份识别制度
2015/08/06 职场文书
2016计算机专业毕业生自荐信
2016/01/28 职场文书
教师节作文之小学四年级
2019/09/03 职场文书
详解JSON.parse和JSON.stringify用法
2022/02/18 Javascript
MySQL串行化隔离级别(间隙锁实现)
2022/06/16 MySQL