【问题标题】:Why does emoji have two different utf-8 codes? How to convert emoji from utf-8 , use NSString in ios?为什么表情符号有两个不同的 utf-8 代码?如何从 utf-8 转换表情符号,在 ios 中使用 NSString?
【发布时间】:2016-03-28 07:39:01
【问题描述】:

我们发现了一个问题,有些表情符号有两个 utf-8 编码,例如:

emoji   unicode    utf-8                another utf-8
????      U+1F601    \xf0\x9f\x98\x81     \xed\xa0\xbd\xed\xb8\x81

但是 ios 语言无法解码其他类型的 utf-8,所以在我从 utf-8 解码字符串时会出错。


在我找到的所有文档中,我只能找到一种用于表情符号的 utf-8 代码,而在哪里可以找到另一种。

我参考的文件包括:

emoji code link

whole utf-8 code link

但是在一个网络工具bianma中,这两种utf-8代码都可以正确转换成emoji。


所以,我的问题是:

  1. 为什么一个 emoji 有两种 utf-8 编码?

  2. 哪里有包含这两种 utf-8 编码的文档?

  3. 如何在ios语言中使用NSString从utf-8正确转换字符串?

【问题讨论】:

  • 这让我很感兴趣,因为我的第一个想法是长 UTF-8 表示是两个 UTF-8 块。事实证明,UTF-8 有两种变体,CESU-8 和 Modified UTF-8,它们编码 UTF-16 样式。如果没有合适的 iOS/Objective-C 原生解码器,你或许可以使用这篇文章iphonedevsdk.com/forum/iphone-sdk-development/… 编写解码器。
  • @AlastairMcCormack 这就是我认为的答案。您应该将其发布为答案。
  • @user692793 请不要将文本作为图像发布,尤其是代码或输出。
  • 谢谢@roeland。我认为正确的答案应该包含一些工作代码,但由于我不是 Objective-C 编码器,所以我会把它留给其他人来获得荣耀:)

标签: ios unicode utf-8 nsstring emoji


【解决方案1】:

0xF0, 0x9F, 0x98, 0x81

U+1F601 是正确的 UTF-8 编码吗?

0xED、0xA0、0xBD、0xED、0xB8、0x81

不是有效的 UTF-8 序列 (*)。真的应该被拒绝; iOS 这样做是正确的。

这是 bianma 工具中的一个错误:convertUtf8BytesToUnicodeCodePoints 函数对于它接受的输入比 RFC 3629 中指定的算法更宽松。

这恰好返回一个工作字符串,只是因为该工具是用 JavaScript 编写的。将上述字节序列解码为伪造的代理代码点序列 U+D83D,U+DE01 后,它使用直接代码点到代码单元的映射将其转换为 JavaScript 字符串,给出\uD83D\xDE01。由于这是在 UTF-16 字符串中编码 ? 的正确方法,因此它似乎有效。

(*:它一个有效的 CESU-8 序列,但这种编码只是“为了与糟糕的历史工具兼容而伪造的损坏编码”,通常应该避免。)

您通常不应该遇到这样的序列;除非您有此类畸形数据的特定来源,而您无权修复,否则通常不值得考虑。

【讨论】:

  • 非常感谢您的回答。我们从使用 C++ 语言的服务器读取字符串数据,在服务器将 unicode 字符串转换为 utf-8 后,会出现此问题。还有一件事需要提到的是,当我们的客户端接收到作为字符串值 cstr 的数据时, printf("%s", cstr) 是正确的。但是当将字符串转换为 NSString 时, NSString *ocstr = [[NSString alloc] initWithBytes:cstr.c_str() length:cstr.length() encoding:NSUTF8StringEncoding]; ocstr 结果为零。为什么苹果不支持 CESU-8 序列?我们有解决问题的功能吗?
  • 我会先看看 C++ 服务器的 UTF-8 编码器,看看它是否可以在源代码上正确修复。 CESU-8 被认为是你永远不会故意使用的不良异常;大多数系统不支持它。如果您必须接受它,则需要编写自己的 CESU-8 解码器遍历输入字节数组(或使用现有库,例如 ICU,尽管这对于这个)。
  • 顺便说一句,有一个特别麻烦的编码源是这样的:JNI(Java Native Interface)。如果您尝试从 Java 字符串中检索“UTF-8”字节,您将收到“修改后的 UTF-8”变体。不幸的是,这是一个相当大的畸形数据来源,无法修复。
【解决方案2】:

这对我在 php 中有用,可以向电报机器人发送带有表情符号的消息:

$message_text = " \xf0\x9f\x98\x81 ";

【讨论】:

  • 这太离题了。
猜你喜欢
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
  • 2016-06-10
  • 2014-08-06
  • 1970-01-01
  • 2019-02-26
  • 2020-09-19
  • 2019-03-21
相关资源
最近更新 更多