`
RednaxelaFX
  • 浏览: 3048183 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

String#unpack对应的UTF-8是怎么回事?

    博客分类:
  • Ruby
阅读更多
Ruby每周一测 - 中英文混合字符串截取

Quake Wang发的这个测试相当有趣,值得一看。我也算是被Ruby的字符编码问题困扰了好段时间了,这次果然又中招了。
老庄的解法:
庄表伟 写道
def truncate_u(text, length = 30, truncate_string = "...")
  l=0
  char_array=text.unpack("U*")
  char_array.each_with_index do |c,i|
    l = l+ (c<127 ? 0.5 : 1)
    if l>=length
      return char_array[0..i].pack("U*")+(i<char_array.length-1 ? truncate_string : "")
    end
  end
  return text
end


看到老庄的解法,我的第一直觉是:UTF-8中CJK应该是三字节的啊,这样unpack之后算出来的值不是不对了么?然后看看RDoc怎么说的:
-------+---------+-----------------------------------------
  U    | Integer | UTF-8 characters as unsigned integers
-------+---------+-----------------------------------------

看到这个文档我还以为是把UTF-8的字符串拆成字节,结果原来是每个字符对应一个整型数字。

可是这个对应关系到底是怎样的……String#unpack的实现在pack.c里:
case 'U':
  if (len > send - s) len = send - s;
  while (len > 0 && s < send) {
    long alen = send - s;
    unsigned long l;
    
    l = utf8_to_uv(s, &alen);
    s += alen; len--;
    rb_ary_push(ary, ULONG2NUM(l));
  }
  break;


然后单个字符的转换函数是:
static unsigned long
utf8_to_uv(p, lenp)
    char *p;
    long *lenp;
{
    int c = *p++ & 0xff;
    unsigned long uv = c;
    long n;

    if (!(uv & 0x80)) {
        *lenp = 1;
            return uv;
    }
    if (!(uv & 0x40)) {
        *lenp = 1;
        rb_raise(rb_eArgError, "malformed UTF-8 character");
    }

    if      (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
    else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
    else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
    else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
    else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
    else {
        *lenp = 1;
        rb_raise(rb_eArgError, "malformed UTF-8 character");
    }
    if (n > *lenp) {
        rb_raise(rb_eArgError, "malformed UTF-8 character (expected %d bytes, given %d bytes)",
             n, *lenp);
    }
    *lenp = n--;
    if (n != 0) {
    while (n--) {
        c = *p++ & 0xff;
        if ((c & 0xc0) != 0x80) {
            *lenp -= n + 1;
            rb_raise(rb_eArgError, "malformed UTF-8 character");
        }
        else {
            c &= 0x3f;
            uv = uv << 6 | c;
        }
    }
    }
    n = *lenp - 1;
    if (uv < utf8_limits[n]) {
        rb_raiserb_eArgError, "redundant UTF-8 sequence");
    }
    return uv;
}

先确定UTF-8字符的长度(字节数),然后在while循环里编码……但是那几个magic number到底是什么意思我还是没弄明白,主要是那个0x3f和6。回去翻翻UTF-8的说明再看看……
分享到:
评论

相关推荐

    sap-me-pack-unpack-how-to-guide-en.pdf

    ### SAP ME Pack and Unpack功能设置与使用指南 #### 概述 本指南旨在为用户提供关于如何在SAP Manufacturing Execution (SAP ME)系统中设置和使用Pack与Unpack功能的详细步骤。此功能主要用于处理制造过程中产品...

    PHP如何实现Unicode和Utf-8编码相互转换

    例如,汉字“你”的码点为0x4F60,转换为二进制为100111101100000,对应的UTF-8编码为E4BDA0。 2. UTF-8转换为Unicode: - 遍历UTF-8字符串,分析每个字节的最高位来确定字符的字节数。 - 对于每个字节,根据其在...

    PyPI 官网下载 | v8unpack-0.6.19-py3-none-any.whl

    **PyPI 官网下载 | v8unpack-0.6.19-py3-none-any.whl** 在Python的世界里,PyPI(Python Package Index)是官方的第三方软件包仓库,它为Python开发者提供了一个发布、查找和安装Python库的平台。`v8unpack`是一个...

    Python库 | v8unpack-0.8.2-py3-none-any.whl

    资源分类:Python库 所属语言:Python 资源全名:v8unpack-0.8.2-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    Python库 | fmrib_unpack-1.3.1-py3-none-any.whl

    资源分类:Python库 所属语言:Python 资源全名:fmrib_unpack-1.3.1-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    Unpack - Has Viruts - Warning_autofunc9yin_

    【标题】"Unpack - Has Virus - Warning_autofunc9yin_" 提示我们这是一个关于解压文件的过程,其中包含了病毒警告,与“autofunc9yin”这个标签相关。在Dota 2这款游戏中,“autofunc9yin”可能是指自动函数或脚本...

    mp-unpack mp-unpack

    "mp-unpack mp-unpack" 这个标题和描述似乎在重复同一个关键词,可能是由于某种原因导致信息不完整。不过,我们可以根据“mp-unpack”这个标签来推测这是关于一个用于解压或处理MP格式文件的工具或者命令。在IT领域...

    Lua UnPack函数用法实例

    在Lua编程语言中,unpack函数是一个非常实用且高效的工具,它主要用于从数组类型的table中解包元素。在本文中,我们将详细介绍unpack函数的用法,包括它的基本功能和如何通过实例来掌握它的使用技巧。 首先,让我们...

    前端开源库-rsa-unpack

    "rsa-unpack"就是这样一个专为前端开发者设计的开源库,它专注于RSA解包,特别是从PEM(Privacy Enhanced Mail)格式的字符串中提取RSA密钥字段。 RSA是一种非对称加密算法,由Ron Rivest、Adi Shamir和Leonard ...

    string-unpack-code.rar_The Test

    This test case unpacks the compressed code for the MochiKit, jQuery, Dojo and Prototype JavaScript libraries.

    av-mp4-unpack-with-mp4v2-master.zip

    使用libmp4v2解封装(demux)出mp4文件中的h264视频数据和aac语音数据

    ethminer-0.16.0.dev3

    Download an archive for your operating system and unpack the content to a place accessible from command line. The ethminer is ready to go. | Builds | Release | Date | | ------ | ------- | ---- | | ...

    Win3.1-on-s60v3_v1.0_(Marcin-prv)_S60cn

    1. Unpack Download1 'DOSBox_S60v3_(Marcin-prv)_S60cn.rar' archiwe to your Memory Card 1. 解压下载地址1的DOSBox_S60v3_(Marcin-prv)_S60cn.rar 并复制到存储卡 2. Install ALL aplication from 'Install' ...

    Themida - Winlicense Ultra Unpacker 1.4.rar_C7X_Unpack_WinLicens

    Themida Unpack Script 2

    apache-maven-3.3.9.rar

    1) Unpack the archive where you would like to store the binaries, eg: Unix-based operating systems (Linux, Solaris and Mac OS X) tar zxvf apache-maven-3.x.y.tar.gz Windows unzip apache-maven-3.x...

    webpack-unpack:从webpack生成的包中提取模块

    webpack解压 从webpack生成的包中提取模块 ...npm install webpack-unpack 用法 管道捆绑到它: $ webpack - unpack (t){console.log(t)},exports.boop n,r,o=module.exports n=0,r&gt;=0;r--){var /*..snip

    Unpack-0.1_win.zip

    这是模拟思科asa防火墙需要用到的文件,网上很难找到了!

Global site tag (gtag.js) - Google Analytics