获取文件编码

4
5个回答

9
检测编码对于所有8位字符集来说都非常困难,除了utf-8(因为不是每个8位字节序列都是有效的utf-8),通常需要语义知识来检测编码。
想象一下:任何特定的纯文本信息只是一堆没有关联编码信息的字节。如果你查看任何特定的字节,它可能意味着任何事情,所以要有机会检测编码,你必须在其他字节的上下文中查看该字节,并尝试基于可能的语言组合进行一些启发式方法。
对于8位字符集,您永远无法确定。
例如,在这里演示启发式方法出错:

http://www.hoax-slayer.com/bush-hid-the-facts-notepad.html

一些16位集合,你有可能检测到它们,因为它们可能包含字节顺序标记或每隔一个字节设置为0。

如果你只想检测UTF-8,你可以使用已经解释过的mb_detect_encoding,或者你可以使用这个方便的小函数:

function isUTF8($string){
    return preg_match('%(?:
    [\xC2-\xDF][\x80-\xBF]        # non-overlong 2-byte
    |\xE0[\xA0-\xBF][\x80-\xBF]               # excluding overlongs
    |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}      # straight 3-byte
    |\xED[\x80-\x9F][\x80-\xBF]               # excluding surrogates
    |\xF0[\x90-\xBF][\x80-\xBF]{2}    # planes 1-3
    |[\xF1-\xF3][\x80-\xBF]{3}                  # planes 4-15
    |\xF4[\x80-\x8F][\x80-\xBF]{2}    # plane 16
    )+%xs', $string);
}

我可以问一下,这个函数是你创建的还是从其他地方复制的? 我想在一些生产代码中使用它,我需要知道它的来源。此外,您能详细说明一下它正在做什么吗?谢谢。 - Gary Willoughby
以下是来自2006年8月3日PHP手册的评论:mb_detect_encoding()函数非常有用,可以检测字符串的编码方式。它可以帮助你在处理多语言网站时避免出现乱码问题。但需要注意的是,该函数并不总是100%准确,因此在使用时还需谨慎。 - pilif

3

mb_detect_encoding可以完成这项工作。

http://us.php.net/manual/en/function.mb-detect-encoding.php

在默认设置下,它只能检测ASCII、UTF-8和一些日语JIS变体。如果您手动指定,它可以配置为检测更多的编码方式。如果一个文件既是ASCII又是UTF-8,则会返回UTF-8。


我不认为你的最后一句话是正确的。如果是这样的话,那么ASCII将永远不会被检测到,因为所有ASCII字符串也都是UTF-8。我认为mb_detect_order()函数是确定在多个编码中返回哪种编码相关的。默认情况下,ASCII排在UTF-8之前。 - Rob Kennedy
根据PHP的文档,它应该是这样工作的,是的。但它似乎并没有。如果它按照文档所说的那样工作,它永远不会返回UTF-8。过去我使用它时,它更喜欢UTF-8而不是ASCII,只有当字符串不是有效的UTF-8字符串时才返回ASCII。 - BlackAura
我不得不使用pilif发布的函数,因为这个函数并不总是返回正确的编码。 - Gary Willoughby

1

除非文件内部某处有提示,否则你无法确定它的编码方式。

例如,HTML 文件应该在顶部附近包含一个 content-type 的 meta 标签,以便您的网络浏览器知道使用的编码方式。例如:

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />

或者

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

有一些方法可以通过查看文件并发现暗示某些编码的字节序列来猜测编码,但这些只是猜测。


0
你可以使用fread()函数查看文件的前几个字节以查找"magic number",然后将该魔数与已知文件类型的魔数列表进行匹配。

1
只有到一个相当有限的程度。UTF-16文件的编码由BOM(字节顺序标记)指示,以区分小端和大端(UTF-16LE和UTF-16BE)。但对于其他代码集,没有强制性的识别 - 它们只需按其编码呈现数据即可。 - Jonathan Leffler

0

我认为BlackAura的建议非常好。

另一个选项是使用system()或类似函数在相关文件上调用file(1)命令。通常,它能够告诉你编码方式。该命令应该适用于任何健全的UNIX环境。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接