【问题标题】:Detect charset of file dynamically in c++在 C++ 中动态检测文件的字符集
【发布时间】:2017-10-10 11:03:01
【问题描述】:

我正在尝试读取可能包含任何字符集/codePage 的文件,但我没有设置哪个区域设置以正确读取文件。

下面是我的代码 sn-p,我在其中尝试读取字符集为 windows-1256 的文件,但我想从正在读取的文件中动态获取字符集,以便我可以相应地设置语言环境。

std::wifstream input{ filename.c_str() };
std::wstring content{ std::istreambuf_iterator<wchar_t>(input1), std::istreambuf_iterator<wchar_t>() };
input.imbue(std::locale(".1256"));
contents = ws2s(content); // Convert wstring to CString

【问题讨论】:

    标签: c++ unicode character-encoding utf icu


    【解决方案1】:

    让我直截了当地说:你不能

    让我来说明一下:一个文件只是大量的 0 和 1 卡在您的磁盘上。字符集是解释这些 0 和 1 的一种方式。 必须提供有关如何解释它们的信息,即通过指定字符集。

    这样做的典型方法是编写一个标头来指定字符集。

    这是一个 html 标头

    <head>
      <title>Page Title</title>
      <meta charset="UTF-8">
    </head>
    

    如您所见,字符集必须以一种或另一种方式指定。

    有时,您确实会看到一些流氓应用程序猜测字符集,他们通常会通过一些启发式方法来猜测字节的分布,但这并不可靠,而且通常会导致乱码。

    作为旁注,请尝试使用UTF-8 everywhere,其他的,说白了就是乱七八糟。

    【讨论】:

      【解决方案2】:

      一般来说,仅使用纯文本文件的内容是不可能准确地做到这一点的。通常你应该依赖一些外部信息。例如,如果文件是使用 HTTP 下载的,则应在响应标头中接收编码。

      某些文件可能包含有关文件格式指定的编码的信息。 XML 例如:&lt;?xml version="1.0" encoding="XXX"?&gt;

      如果文件以字节顺序标记开头 - 这是可选的,则可以检测到 Unicode 编码。

      如果文件在文件结尾之前包含一个零字节(将字符串终止符表示为窄字符),您通常可以假设编码使用宽字符。同样,如果您发现两个连续的零与 2 字节边界对齐(在结尾之前),那么编码可能是 4 字节宽。

      除此之外,您可以尝试根据某些字符的频率来猜测编码。这可以有一些unintended consequences

      【讨论】:

      • 没有确定字符集的完整证明方法,但我们可以为此使用 ICU 库,它提供了基于启发式的解决方案。我使用了来自github.com/mooz/node-icu-charset-detector/blob/master/… 的 sn-p
      • @SaurabhKathpalia 是的,外包给图书馆是节省时间和精力的好方法。请记住基于启发式方法的潜在陷阱(我的答案的最后一个链接是此类陷阱的实际示例)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多