读取未知字符类型的文件

Read file with unknown character type

我需要从可能包含任何类型字符(charchar8_twchar_t 等)的文件中读取文本。我如何确定使用哪种类型的字符并根据该类型创建 basic_ifstream<char_type> 的实例?

无法确定。您必须被告知字符类型是什么。文本文件通常以 Byte-Order-Mark 开头以提示您,但即使这样也并非万无一失。

你可以对文件内容进行合理的猜测,例如,如果你“知道”其中大部分是ASCII范围的文本,那么应该很容易猜到如果文件充满 charwchar_t 个字符,则输出。即使这依赖于假设,也不应该被认为是无懈可击的。

所以我猜您想自动检测未知文本文件的编码。

这不可能以 100% 可靠的方式做到。然而,我的经验表明,在大多数实际情况下,您可以获得非常高的可靠性 (> 99.99%)。文件越大,猜测它的编码最可靠:十分之几字节通常已经足够相信猜测了。

有效的 Unicode 代码点是从 U+1 到 U+10FFFF 的值,不包括代理范围 U+D800 到 U+DFFF。代码点 U+0 实际上是有效的,但排除它会大大减少误报的数量(NUL 字节永远不应该出现在任何实际的文本文件中)。为了更好地猜测,我们可以排除一些更罕见的控制字符。

这是我建议的算法:

  • 如果文件以有效的 BOM(UTF-8、UTF-16BE/LE、UTF-32BE/LE)开头,请相信该 BOM。
  • 如果文件仅包含 ASCII 字符(非空字节 < 128),则将其视为 ASCII(使用 char)。
  • 如果文件是 valid UTF-8,则假定它是 UTF-8(使用 char8_t,但 char 也可以)。请注意,ASCII 是 UTF-8 的子集,因此可以绕过前面的检查。
  • 如果文件是有效的 UTF-32(检查小端和大端版本),则假定为 UTF-32(char32_t,在 Linux 或 macOS 上也可能是 wchar_t ).如果需要交换字节。
  • 如果文件是有效的 UTF-16(同时检查小端和大端版本),包括对代理项对的限制,并且偶数或奇数字节之间的相关性高于所有字节之间的相关性,则假定 UTF-16 (char16_t,Windows 上可能还有 wchar_t。如果需要交换字节。
  • 否则,该文件可能不是某些 Unicode 编码,并且可能使用旧代码页。祝你好运自动检测哪一个。目前比较常见的是 8859-1 (Latin-1),使用 char。它也可能是一些原始二进制数据。