读取未知字符类型的文件
Read file with unknown character type
我需要从可能包含任何类型字符(char
、char8_t
、wchar_t
等)的文件中读取文本。我如何确定使用哪种类型的字符并根据该类型创建 basic_ifstream<char_type>
的实例?
无法确定。您必须被告知字符类型是什么。文本文件通常以 Byte-Order-Mark 开头以提示您,但即使这样也并非万无一失。
你可以对文件内容进行合理的猜测,例如,如果你“知道”其中大部分是ASCII范围的文本,那么应该很容易猜到如果文件充满 char
或 wchar_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
。它也可能是一些原始二进制数据。
我需要从可能包含任何类型字符(char
、char8_t
、wchar_t
等)的文件中读取文本。我如何确定使用哪种类型的字符并根据该类型创建 basic_ifstream<char_type>
的实例?
无法确定。您必须被告知字符类型是什么。文本文件通常以 Byte-Order-Mark 开头以提示您,但即使这样也并非万无一失。
你可以对文件内容进行合理的猜测,例如,如果你“知道”其中大部分是ASCII范围的文本,那么应该很容易猜到如果文件充满 char
或 wchar_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
。它也可能是一些原始二进制数据。