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 相关文章推荐
Node.js中require的工作原理浅析
Jun 24 Javascript
基于jquery实现等比缩放图片
Dec 03 Javascript
简介BootStrap model弹出框的使用
Apr 27 Javascript
EasyUI布局 高度自适应
Jun 04 Javascript
jQuery插件扩展测试实例
Jun 21 Javascript
Jquery调用iframe父页面中的元素及方法
Aug 23 Javascript
Vue.js 插件开发详解
Mar 29 Javascript
vue通过点击事件读取音频文件的方法
May 30 Javascript
vue修改对象的属性值后页面不重新渲染的实例
Aug 09 Javascript
JavaScript编写开发动态时钟
Jul 29 Javascript
javascript实现打砖块小游戏(附完整源码)
Sep 18 Javascript
JavaScript如何实现防止重复的网络请求的示例
Jan 28 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
PHP 程序员应该使用的10个组件
2009/10/31 PHP
THINKPHP+JS实现缩放图片式截图的实现
2010/03/07 PHP
用穿越火线快速入门php面向对象
2012/02/22 PHP
Thinkphp中import的几个用法详细介绍
2014/07/02 PHP
微信自定义分享php代码分析
2016/11/24 PHP
jQuery编辑器KindEditor4.1.4代码高亮显示设置教程
2013/03/01 Javascript
jquery 循环显示div的示例代码
2013/10/18 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 简史
2015/01/09 Javascript
jQuery超精致图片轮播幻灯片特效代码分享
2015/09/10 Javascript
js 截取或者替换字符串中的数字实现方法
2016/06/13 Javascript
浅谈js对象的创建和对6种继承模式的理解和遐想
2016/10/16 Javascript
JavaScript实现的商品抢购倒计时功能示例
2017/04/17 Javascript
js-FCC算法-No repeats please字符串的全排列(详解)
2017/05/02 Javascript
layui文件上传实现代码
2017/05/20 Javascript
深入浅析Vue.js计算属性和侦听器
2018/05/05 Javascript
node.js中fs文件系统模块的使用方法实例详解
2020/02/13 Javascript
antd配置config-overrides.js文件的操作
2020/10/31 Javascript
[01:32:22]DOTA2-DPC中国联赛 正赛 Ehome vs VG BO3 第一场 2月5日
2021/03/11 DOTA
Python实用日期时间处理方法汇总
2015/05/09 Python
Python简单的制作图片验证码实例
2017/05/31 Python
pygame游戏之旅 调用按钮实现游戏开始功能
2018/11/21 Python
Python Pandas分组聚合的实现方法
2019/07/02 Python
Python模块zipfile原理及使用方法详解
2020/08/04 Python
canvas实现圆绘制的示例代码
2019/09/11 HTML / CSS
美国排名第一的葡萄酒俱乐部:Firstleaf Wine Club
2020/01/02 全球购物
会计学财务管理专业个人的自我评价
2013/10/19 职场文书
数控专业推荐信范文
2013/12/02 职场文书
校园达人秀策划书
2014/01/12 职场文书
副科竞争上岗演讲稿
2014/05/12 职场文书
知识竞赛拉拉队口号
2014/06/16 职场文书
2014年酒店工作总结与计划
2014/11/17 职场文书
明星邀请函
2015/02/02 职场文书
漂亮妈妈观后感
2015/06/08 职场文书
小王子读书笔记
2015/06/29 职场文书
python实现调用摄像头并拍照发邮箱
2021/04/27 Python
我对PyTorch dataloader里的shuffle=True的理解
2021/05/20 Python