在C ++中动态检测文件的字符集

Detect charset of file dynamically in c++

我正在尝试读取一个可能包含 charset/codePage 的文件,但我不知道要设置哪个语言环境才能正确读取文件。

下面是我的代码片段,我在其中尝试读取一个字符集为 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

让我直言不讳地说:你不能

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

一种典型的做法是编写 header 来指定字符集。

这是一个htmlheader

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

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

偶尔,您确实会看到一些流氓应用程序猜测字符集,他们通常会通过一些关于字节分布的试探法来这样做,但这并不可靠,而且经常会导致乱码。

作为旁注,尝试使用UTF-8 everywhere,其他的,说得轻一点,很乱。

一般情况下,仅使用纯文本文件的内容是无法准确做到这一点的。通常你应该依赖一些外部信息。例如,如果文件是通过 HTTP 下载的,则应在响应 header.

中接收编码

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

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

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

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