代码之家  ›  专栏  ›  技术社区  ›  Kerry Jones

__编码到UTF-8-是否有一个完整的解决方案?

  •  4
  • Kerry Jones  · 技术社区  · 14 年前

    我已经浏览了整个网络,也浏览了一些PHP文档等等。

    没有标准的解决方案似乎是一个荒谬的问题。如果您得到一个未知的字符集,并且它有奇怪的字符(如英文引号),有没有一种标准的方法将它们转换为UTF-8?

    我看到过许多混乱的解决方案使用了过多的函数和检查,它们中没有一个肯定会起作用。

    是否有人想出了自己的功能或始终有效的解决方案?


    编辑

    许多人回答说,“这是不可解决的”或类似的性质。我现在明白了,但是没有人给出任何解决办法 utf8_encode 这是非常有限的。有什么方法可以解决这个问题?什么是 最好的 方法?

    4 回复  |  直到 13 年前
        1
  •  9
  •   cdonner    14 年前

    对于这个问题,你看到这么多复杂的解决方案的原因是,根据定义,它是不可解决的。对字符串进行编码的过程是不确定的。 可以构造不同的文本和编码组合,从而产生相同的字节流。因此,严格从逻辑上讲,不可能从字节流中确定编码、字符集和文本。

    实际上,使用启发式方法可以获得“足够接近”的结果,因为在野外会遇到一组有限的编码,并且有足够大的样本,程序可以确定最可能的编码。结果是否足够好取决于应用程序。

    我想对用户生成数据的问题发表评论。从一个网页发布的所有数据都有一个已知的编码(该文章带有开发人员为该网页定义的编码)。如果用户将文本粘贴到表单字段中,浏览器将根据源数据的编码(如操作系统所知)和页面编码来解释文本,并在必要时对其进行转码。检测服务器上的编码为时已晚,因为浏览器可能已根据假定的编码修改了字节流。

    例如,如果我在我的德语键盘上键入字母_1001并将其发布到一个UTF-8编码的页面上,将有2个字节(xc3 x84)发送到服务器。这是表示字母C和D的有效EBCDIC字符串。这也是表示2个字符_和__的有效ANSI字符串。然而,无论我怎么尝试,都不可能将一个ANSI编码的字符串粘贴到浏览器表单中,并期望它被解释为UTF-8-因为操作系统知道我正在粘贴ANSI(我从创建了一个ANSI编码文本文件的textpad中复制了文本),并将其转换为UTF-8,从而导致字节流xc3 x83XE2-X80X9E。

    我的观点是,如果一个用户设法发布垃圾,那有可能是因为在将垃圾粘贴到浏览器表单时,它已经是垃圾了,因为客户端对字符集、编码等没有适当的支持。 因为字符编码是非确定性的,所以您不能期望从这种情况中发现一个微不足道的方法。

    不幸的是,对于上载的文件,问题仍然存在。我看到的唯一可靠的解决方案是向用户显示文件的一部分并询问它是否被正确解释,然后循环使用一系列不同的编码,直到出现这种情况。

    或者我们可以开发一种启发式的方法来观察某些字符在各种语言中的出现。假设我上传了包含两个字节xc3 x84的文本文件。没有其他信息-文件中只有两个字节。这种方法可以发现,字母_在德语文本中相当常见,但字母_和_在任何语言中都不常见,因此确定我的文件编码确实是UTF-8。这一粗略程度是这种启发式方法必须处理的复杂程度,而且它可以使用的统计和语言事实越多,其结果就越可靠。

        2
  •  11
  •   Pekka    14 年前

    不应该。人们应该总是知道字符串的字符集是什么。使用嗅探函数猜测字符集是不可靠的(尽管在大多数情况下,在西方世界,它通常是ISO-8859-1和UTF-8之间的混合)。

    但你为什么要处理未知的字符集呢?没有一般的解决办法,因为一般的问题不应该首先存在。每个网页和数据源都可以并且应该有一个字符集定义,如果没有,应该请求该资源的管理员添加一个字符集定义。

    (听起来不像个聪明人,但 处理好这件事的唯一方法。)

        3
  •  1
  •   Dereleased    14 年前

    Pekka对不可靠性的看法是正确的,但是如果您需要一个解决方案并且愿意承担风险,并且您有可用的mbstring库,那么这个片段应该可以工作:

    function forceToUtf8($string) {
        if (!mb_check_encoding($string)) {
            return false;
        }
        return mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string));
    } 
    
        4
  •  0
  •   Francesco Belladonna    14 年前

    如果我没有错,有一种叫做utf8encode的东西…它工作得很好,除非您已经使用了UTF8

    http://php.net/manual/en/function.utf8-encode.php