【问题标题】:Different utf8 encodings?不同的utf8编码?
【发布时间】:2013-04-10 13:45:03
【问题描述】:

我有一个 utf8 编码的小问题。 我尝试编码的词是“kühl”。 所以它有一个特殊的字符。

当我在我得到的第一个文件中用 utf8 编码这个字符串时:

kühl

当我在第二个文件中用 utf8 编码这个字符串时,我得到:

ku�hl

使用 php utf8_encode() 我总是将第一个 (kühl) 作为输出,但我需要第二个作为输出 (kuÌ�hl)。

mb_detect_encoding 告诉我它是“UTF-8”,所以这并没有真正的帮助。

您有什么想法可以将第二个作为输出吗? 提前致谢!

【问题讨论】:

  • 当我在 notepad++ 中检查 kühl 并选择 UTF-8 时,没问题。第二个好像很奇怪。
  • 知道第二个可能是什么吗?我不明白为什么 mb_detect_encoding 告诉我它也是 UTF-8
  • 我假设您的脚本文件是使用不同的字符编码保存的——因此在这两种情况下,您实际上并不是对相同的字节序列进行 UTF8 编码,而是对不同的字节序列进行编码。
  • 也这么认为,但这不是问题。知道第二个可能是哪种编码吗?
  • 在“kuÌ�hl”中,我看到一个 U+00CC“带有坟墓的拉丁大写字母 I”,后跟一个 U+FFFD“替换字符”;后者看起来像黑色菱形中的白色问号。无论您的字符串中有什么数据,其中一些数据在传输到我的浏览器的过程中都会丢失。

标签: php utf-8 character-encoding


【解决方案1】:

只有一种编码称为 UTF-8,但有多种方法可以表示 Unicode 中的某些字形。 U+00FC 是拉丁语 1 兼容的单字形预组合 ü,在拉丁语 1 中显示为 kühl,而 在我的头顶 kuÌ�hl 看起来像是同一个字符的完全分解的表达式,即U+0075 (u) 后跟U+0308(结合分音符)。另见http://en.wikipedia.org/wiki/Unicode_equivalence#Normalization

vbvntv$ perl -CSD -le 'print "ku\x{0308}hl"' | iconv -f latin1 -t utf8
ku�hl
vbvntv$ perl -CSD -le 'print "ku\x{0308}hl"' | xxd
0000000: 6b75 cc88 686c 0a                   ku..hl.

0x88 不是 Latin-1 中的有效字符,因此(在我的浏览器中)它显示为“无效字符”占位符(带有白色问号的黑色菱形),而其他人可能会看到其他内容,或者什么也看不到.

显然你可以在 PHP 中使用class.normalize 在这两种形式之间进行转换:

$normalized = Normalizer::normalize($input, Normalizer::FORM_D);

顺便说一句,将 UTF8 视为 Latin-1 并复制/粘贴表示,就好像它是实际的真实文本一样,充其量是反复无常的。如果您有字符编码问题,实际字节(例如,十六进制)是表达您所拥有内容的唯一可移植、可理解的方式。在许多情况下,您的计算机如何呈现它是不可预测的,尤其是当编码有问题或未知时。我坚持使用您在问题中使用的演示文稿,但如果您还有其他问题,请注意清楚地阐明问题。

【讨论】:

  • 我希望支持将 UTF-8 提供给 iconv 并告诉它将 Latin-1 转换为 UTF-8 以便在我的 UTF-8 终端。
  • 如果我错了,请纠正我,但这是 NFC 与 NFD 的问题吗?虽然这个答案非常具有描述性,但它并没有真正回答 OP 提出的问题,即如何在 NFD 中获取它。
  • @Phil_1984_ 感谢您指出这一点!添加了一个 PHP 的 sn-p 来做到这一点。
【解决方案2】:

utf8_encode,尽管它的名字,并不会神奇地编码成 UTF-8。

只有在您的来源是 ISO-8559-1(也称为 latin-1)时才有效。

如果您的源已经是 UTF-8 或任何其他编码,它将输出损坏的数据。

【讨论】:

    猜你喜欢
    • 2012-02-20
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多