4

我浏览过网络,浏览过 SO,浏览过 PHP 文档等等。

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

我见过许多使用过多功能和检查的混乱解决方案,但没有一个肯定会起作用。

有没有人提出自己的功能或始终有效的解决方案?


编辑

许多人回答说“它无法解决”或类似的东西。utf8_encode我现在明白了,但是除了非常有限之外,没有人给出任何有效的解决方案。有什么方法可以解决这个问题?最好的方法是什么?

4

4 回答 4

11

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

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

(听起来不像是个聪明人,但这解决这个问题的唯一方法。)

于 2010-06-11T21:05:01.610 回答
9

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

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

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

例如,如果我在德语键盘上键入字母 Ä 并将其发布到 UTF-8 编码的页面上,则将有 2 个字节 (xC3 x84) 发送到服务器。这是表示字母 C 和 d 的有效 EBCDIC 字符串。这也是一个有效的 ANSI 字符串,表示 2 个字符 Ã 和 „。但是,无论我如何尝试,都不可能将 ANSI 编码的字符串粘贴到浏览器表单中并期望它被解释为 UTF-8 - 因为操作系统知道我正在粘贴 ANSI(我复制了我在其中创建了一个 ANSI 编码的文本文件的 Textpad 中的文本)并将其转码为 UTF-8,从而生成字节流 xC3 x83 xE2 x80 x9E。

我的观点是,如果用户设法发布垃圾,可以说是因为它在粘贴到浏览器表单时已经是垃圾,因为客户端没有对字符集、编码等任何适当的支持。因为字符编码是不确定的,所以你不能指望有一种简单的方法可以从这种情况中发现。

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

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

于 2010-06-14T01:14:05.930 回答
1

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

function forceToUtf8($string) {
    if (!mb_check_encoding($string)) {
        return false;
    }
    return mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string));
} 
于 2010-06-11T21:11:42.247 回答
0

如果我没记错的话,有一个叫做 utf8encode 的东西......它工作得很好,除非你已经在 utf8

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

于 2010-06-14T01:57:17.763 回答