7

各种字符编码的一个问题是包含文件并不总是被清楚地标记。使用“字节顺序标记”或 BOM 标记某些内容的约定不一致。但本质上,您必须被告知文件编码是什么,才能准确读取它。

我们构建了读取源文件的编程工具,这让我们很伤心。我们有办法指定默认值,并嗅探 BOM 等。而且我们在约定和默认值方面做得很好。但是我们(我假设其他所有人)挂断的地方是没有 BOM 标记的 UTF-8 文件。

最近的 MS IDE(例如,VS Studio 2010)显然会“嗅探”文件以确定它是否是 UTF-8 编码而没有 BOM。(在工具业务中,我们希望与 MS 兼容,因为它们的市场份额,即使这意味着必须与他们一起越过“愚蠢”的悬崖。)我对他们使用什么特别感兴趣启发式(尽管启发式的讨论很好)?怎么可能是“对的”?(考虑以这种方式解释的 ISO8859-x 编码字符串)。

编辑:这篇关于检测字符编码/集的论文非常有趣: http ://www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html

编辑 2012 年 12 月:我们结束了对整个文件的扫描,以查看它是否包含任何违反 UTF-8 序列的行为……如果没有,我们将其称为 UTF-8。该解决方案的坏处是,如果字符是 UTF-8,则必须处理两次字符。(如果不是 UTF-8,这个测试可能会很快确定,除非文件发生在所有 7 位 ASCII 上,此时像 UTF-8 一样读取不会受到伤害)。

4

3 回答 3

8

如果编码是 UTF-8,那么您在 0x7F 上看到的第一个字符必须是 UTF-8 序列的开头。所以测试它。这是我们使用的代码:

unc ::IsUTF8(unc *cpt)
{
    if (!cpt)
        return 0;

    if ((*cpt & 0xF8) == 0xF0) { // start of 4-byte sequence
        if (((*(cpt + 1) & 0xC0) == 0x80)
         && ((*(cpt + 2) & 0xC0) == 0x80)
         && ((*(cpt + 3) & 0xC0) == 0x80))
            return 4;
    }
    else if ((*cpt & 0xF0) == 0xE0) { // start of 3-byte sequence
        if (((*(cpt + 1) & 0xC0) == 0x80)
         && ((*(cpt + 2) & 0xC0) == 0x80))
            return 3;
    }
    else if ((*cpt & 0xE0) == 0xC0) { // start of 2-byte sequence
        if ((*(cpt + 1) & 0xC0) == 0x80)
            return 2;
    }
    return 0;
}

如果返回 0,则它不是有效的 UTF-8。否则跳过返回的字符数并继续检查下一个超过 0x7F 的字符。

于 2013-02-16T17:41:23.823 回答
2

Visual Studio Code 使用jschardet,它返回猜测值和置信度。它都是开源的,所以你可以检查代码。

https://github.com/microsoft/vscode/issues/101930#issuecomment-655565813

于 2020-12-09T21:13:41.283 回答
1

我们刚刚找到了解决方案基本上,当您不知道文件/流/源的编码时,您需要检查整个文件和/或查找部分文本以查看是否获得 UTF-8 匹配。我看到这类似于某些抗病毒产品的作用,检查已知病毒子串的部分

也许我建议您将调用应用于类似于我们在读取文件/流时所做的函数,逐行确定是否找到 UTF-8 编码

请参考我们下面的帖子

参考。- https://stackoverflow.com/questions/17283872/how-to-detect-utf-8-based-encoded-strings

于 2013-06-24T20:46:02.160 回答