Java:单个代码点的UTF-8字节长度(代理再次)

时间:2015-07-15 01:09:59

标签: java utf-8 character-encoding

这一切都是一个非常基本的问题:给定char - 或者更确切地说,整数代码点,请参阅Character API - ,返回其UTF-8编码所需的字节数。然而,我花在这个无辜的小问题上的时间越多,它变得越混乱。

我的第一个方法是:

int getUtf8ByteCount_stdlib(int codePoint) {
    int[] codePoints = { codePoint };
    String string = new String(codePoints, 0, 1);
    byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
    return bytes.length;
}

或者喜欢它的人:

int getUtf8ByteCount_obfuscated(int codePoint) {
    return new String(new int[] { codePoint }, 0, 1).getBytes(StandardCharsets.UTF_8).length;
}

然后我创建了另一个版本(基于UTF-8 wikipedia article),以简化和提高效率:

int getUtf8ByteCount_handRolled(int codePoint) {
    if (codePoint > 0x7FFFFFFF) {
        throw new IllegalArgumentException("invalid UTF-8 code point");
    }
    return codePoint <= 0x7F? 1
         : codePoint <= 0x7FF? 2
         : codePoint <= 0xFFFF? 3
         : codePoint <= 0x1FFFFF? 4
         : codePoint <= 0x3FFFFFF? 5
         : 6;
}

经过多年努力与字符编码的许多可爱的微妙之处,我跑了一个测试,然后!它失败了;对于来自&#39; \ uD800&#39;的所有代码点&#39; \ uDFFF&#39;,&#34; stdlib&#34;版本返回1个字节而3个字节用于&#34;手动滚动&#34;。当然,这是好事。代理人物再次造成破坏!现在,根据我对那些讨厌的小虫子的理解,我会说第二个版本是正确的。我的问题:

  1. String.getBytes()还是(Java的UTF-8实施)被破坏了,还是我的理解? (我使用的是Oracle Java SE Runtime Environment 1.6.0_22-b04)
  2. 即使不正确,最好是手工制作&#34;该版本与Java的UTF-8生成的实际字节编码/解码更加一致?
  3. 除了正确性考虑之外,Java标准库是否提供了比我的&#34; stlib&#34;更清晰的方式。一个?

0 个答案:

没有答案