【问题标题】:Properly handling escaped unicode characters in php正确处理 php 中的转义 unicode 字符
【发布时间】:2013-09-05 09:54:06
【问题描述】:

我使用 php 解析一个包含 unicode 字符的文本文件,例如 ????

只需读入文件,无需任何进一步的编码/解码,笑脸被解析,然后 json_encoded 输出为\u00f0\u009f\u0098\u008d

一个 javascript 文件获取 .json 数据并将 4 个转义字符输出为 ð

查看 unicode 表,该符号称为“心形眼睛的微笑脸”,其 unicode 编号为 U+1F60D (128525)

有没有办法将 4 个代码单元转换为 unicodenumber 或理想情况下转换为适当的 html 编码方式,在本例中为 😍

查看转换,utf 8 代码单元看起来相似(F0 9F 98 8D 0A 0A),但我无法重现我得到的 4 个转义单元,所以我什至不知道我在看什么

更新:我弄错了,编辑了第二段:\u00f0\u009f\u0098\u008d已经是json_encode()的结果;

这是从文件中读取数据的基本功能,查看笑脸是“硬编码”的源代码,所以你真的看到了

function readLocalFile() {
  $file_html = fopen('output.html', "r");
  $html = "";

  while(!feof($file_html)) {
    $html .= fgets($file_html);
  }

  fclose($file_html);

  // here I use regex to filter for specific tags, the result is an array
  $cleanData = parseData($html);

  saveToFile(json_encode($cleanData)); 
}

我刚刚创建了一个只有 ???? 作为内容的 dummy.html,这会返回正确的结果 \ud83d\ude0d,在整个数据的上下文中,它仍然如上所述被破坏,很奇怪

我得看看数据保存到output.html的方式,这就是问题所在。我一直在看问题的错误部分,哦!

上次更新:终于找到错误了。它在 parseData-function 中,loadHTML 以某种方式混淆了内容,在这里找到了解决方案: PHP DOMDocument loadHTML not encoding UTF-8 correctly

【问题讨论】:

  • 这个 IS UTF-8,末尾的 0A 0A 已经是下一个字符(CR 或 LF)了。
  • 您的输入字符串已损坏,\u00f0\u009f\u0098\u008d 显然不是 U+1F60D,因为那将是\ud83d\ude0d。你应该看看为什么你在输入字符串中有这个。这看起来有点像从 UTF-8 到 JSON 的被误解的“转换”,可能是由于 PHP json unicode 处理损坏(#62010?)你应该分享一些代码来说明更多。
  • 刚刚看到您的编辑。在将json_encode 传递给json_encode 之前,您能否提供the string hex-encoded 的样本?如果它很长或包含私人信息,也许只需将其减少到造成问题的部分。

标签: php unicode


【解决方案1】:

你的问题让我感到困惑的是\u00f0\u009f\u0098\u008d 序列。它只是听起来不像任何标准化的东西。

正如你所写,这是关于 Unicode Character 'SMILING FACE WITH HEART-SHAPED EYES' (U+1F60D)。您提供的基于 \u 的符号似乎表明这将是 Javascript / JSON 编码的 unicode 字符。所以让我们回顾一下:

  • JSON 对不在基本多语言平面(U+0000 到 U+FFFF)中的任何内容使用 UTF-16 代理对。
  • U+1F60D 不在基本多语言窗格中。
  • 它是 UTF-16 编码因此是 0xD83D 0xDE0D
  • 这不是你所拥有的
  • 它的UTF-8编码是xF0 0x9F 0x98 0x8D
  • 这看起来像是您误用的。

经过快速分析,答案如下:如果您可以认为所有\u???? 序列同样被误用于编码 UTF-8 二进制序列,那么您需要做的就是挂钩每个,结合以最后一个十六进制数字编码的字符,即末尾的两个十六进制数字对(位置 5+6 / 索引 4+5)并将其放在一起。

由于这似乎已损坏,我不建议在这里使用完整源代码,因为我不想特别支持这种做法 - 您需要在编码中修复它 - 但是您可以在@987654322 的答案中找到概述的代码@。

所以修复包含错误\u 的输入字符串(u 在这里代表 unicode,但在你的情况下不是因为那些暗示 UTF-16 not 二进制八位字节)。您需要了解这些错误的\u 序列是在哪里引入的,您的问题并不清楚。

【讨论】:

    【解决方案2】:

    您所拥有的是将 UTF-8 数据解码为 ISO-8859-1 (latin1) 到 Unicode,然后进行 JSON 编码。如果你:

    1. 将 JSON 解码为 Unicode。
    2. 使用 latin-1 编码为字节。
    3. 使用 UTF-8 解码为 Unicode。

    这应该给你正确的字符。我不做 PHP,但这里有一个 Python 证明:

    >>> '\u00f0\u009f\u0098\u008d'.encode('latin1').decode('utf8')
    '\U0001f60d'
    >>> import unicodedata as ud
    >>> ud.name('\U0001f60d')
    'SMILING FACE WITH HEART-SHAPED EYES'
    

    数据首先出现乱码的原因可能是 HTML 实际上是 UTF-8 编码的,但错误地声明了 ISO-8859-1 或 Windows-1252。

    【讨论】:

    • 感谢您的解释!我使用了 loadHTML(),它默认处理了我作为 ISO-8859-1 提供的 html 文档,所以我必须将它声明为 UTF-8 文档!据我所知,“DOMDocument 和 loadHTML 存在乱码 UTF-8 内容的问题”。这个答案帮助了我:stackoverflow.com/a/8218649/2748220
    猜你喜欢
    • 2023-02-17
    • 1970-01-01
    • 2018-12-16
    • 2021-01-12
    • 2011-02-22
    • 2014-05-20
    • 1970-01-01
    • 2011-10-30
    • 2011-06-19
    相关资源
    最近更新 更多