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 相关文章推荐
Javascript实现的分页函数
Feb 07 Javascript
基于jquery的Repeater实现代码
Jul 17 Javascript
基于Jquery的动态创建DOM元素的代码
Dec 28 Javascript
jQuery为iframe的body添加click事件的实现代码
Apr 07 Javascript
javascript中类的定义及其方式(《javascript高级程序设计》学习笔记)
Jul 04 Javascript
window.opener用法和用途实例介绍
Aug 19 Javascript
javascript实现在下拉列表中显示多级树形菜单的方法
Aug 12 Javascript
网页从弹窗页面单选框传值至父页面代码分享
Sep 29 Javascript
JS中使用 after 伪类清除浮动实例
Mar 01 Javascript
vue之数据交互实例代码
Jun 16 Javascript
vue.js实现照片放大功能
Jun 23 Javascript
微信小程序实现点赞业务
Feb 10 Javascript
详解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
中国第一家无线电行
2021/03/01 无线电
最新用php获取谷歌PR值算法,附上php查询PR值代码示例
2011/12/25 PHP
php+html5使用FormData对象提交表单及上传图片的方法
2015/02/11 PHP
PHP实现本地图片转base64格式并上传
2020/05/29 PHP
js onpropertychange输入框 事件获取属性
2009/03/26 Javascript
JavaScript Cookie 直接浏览网站分网址
2009/12/08 Javascript
html页面显示年月日时分秒和星期几的两种方式
2013/08/20 Javascript
使用jQuery制作基础的Web图片轮播效果
2016/04/22 Javascript
javascript九宫格图片随机打乱位置的实现方法
2017/03/15 Javascript
React路由管理之React Router总结
2018/05/10 Javascript
详解webpack的proxyTable无效的解决方案
2018/06/15 Javascript
原生js拖拽功能制作滑动条实例代码
2021/02/05 Javascript
[36:33]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第二场 11.29
2020/12/02 DOTA
python 生成不重复的随机数的代码
2011/05/15 Python
python实现多线程暴力破解登陆路由器功能代码分享
2015/01/04 Python
简单理解Python中的装饰器
2015/07/31 Python
python日期相关操作实例小结
2019/06/24 Python
python队列原理及实现方法示例
2019/11/27 Python
Python 虚拟环境工作原理解析
2020/12/24 Python
python生成word合同的实例方法
2021/01/12 Python
HTML5中通过li-canvas轻松实现单图、多图、圆角图绘制,单行文字、多行文字等
2018/11/30 HTML / CSS
使用spring mvc+localResizeIMG实现HTML5端图片压缩上传的功能
2016/12/16 HTML / CSS
Marks & Spencer爱尔兰:英国马莎百货
2016/04/20 全球购物
Supersmart英国:欧洲市场首批食品补充剂供应商之一
2018/05/05 全球购物
加拿大在线眼镜零售商:SmartBuyGlasses加拿大
2019/05/25 全球购物
医药工作者的求职信范文
2013/09/21 职场文书
求职意向书
2014/04/01 职场文书
机关党建工作汇报材料
2014/08/20 职场文书
大学生党员学习焦裕禄精神思想汇报
2014/09/10 职场文书
学习三严三实对照检查材料思想汇报
2014/09/22 职场文书
初中差生评语
2014/12/29 职场文书
2015年新农村建设工作总结
2015/05/22 职场文书
计算机实训心得体会
2016/01/14 职场文书
火锅店的开业营销方案范本!
2019/07/05 职场文书
乔迁新居祝福语
2019/11/04 职场文书
DIY胆机必读:各国电子管评价
2022/04/06 无线电