1

我想使用 Visual Studio 2017、C++ 和 WindowsAPI(以前称为 Win32)为自己编写一个语言学习应用程序。操作系统是最新的 Windows 10 内部版本,向后兼容性不是问题。由于我假设英语是用户的母语,而我目前感兴趣的语言是另一种欧洲语言,ASCII 可能就足够了。但我想对它进行未来验证(更多异国情调的语言),我也想尝试使用 UTF-32。我以前使用过 UTF-8 和 UTF-16,虽然我对后者有更多的经验。

感谢std::basic_string,很容易弄清楚如何获取 UTF-32 字符串:

typedef std::basic_string<char32_t> stringUTF32

由于我为所有 GUI 人员使用 WinAPI,我需要在 UTF-32 和 UTF-16 之间进行一些转换。

现在我的问题是:由于 UTF-32 效率低下而没有被广泛使用,因此网络上几乎没有任何关于它的资料。为了避免不必要的转换,我想将我的词汇表和其他数据保存为 UTF-32(对于所有 UTF-8 倡导者/传播者,替代方案是 UTF-16)。问题是,我找不到如何以 UTF-32 编写和打开文件。

所以我的问题是:如何用 UTF-32 编写/打开文件?我希望不需要第三方库,除非它们是 Windows 的一部分或通常随该操作系统一起提供。

4

2 回答 2

1

如果您有一个char32_t序列,您可以使用 a 将其写入文件std::basic_ofstream<char32_t>(我将其称为u32_ofstream,但此 typedef 不存在)。这与 完全一样std::ofstream,只是它写char32_t的是 s 而不是chars。但也有局限性。

大多数具有operator<<重载的标准库类型都以字符类型为模板。所以他们会u32_ofstream很好地工作。您将遇到的问题是针对用户类型的。这些几乎总是假设您正在编写char,因此被定义为ostream &operator<<(ostream &os, ...);u32_ofstream如果没有转换层,这样的流输出就无法工作。

但是您将面临的大问题是字节序问题。u32_ofstream将编写char32_t为您平台的本机字节序。如果您的应用程序通过 a 读回它们u32_ifstream,那很好。但是如果其他应用程序读取它们,或者如果您的应用程序需要读取其他人以 UTF-32 编写的内容,这就会成为问题。

典型的解决方案是使用“字节顺序标记”作为文件的第一个字符。Unicode 甚至为此预留了一个特定的代码点:\U0000FEFF.

BOM 的工作方式是这样的。编写文件时,您在任何其他代码点之前编写 BOM。

读取未知编码的文件时,您可以正常读取第一个代码点。如果它在您的本机编码中等于 BOM,那么您可以正常读取文件的其余部分。如果没有,那么您需要先读取文件并进行字节序转换,然后才能处理它。该过程看起来像这样:

constexpr char32_t native_bom = U'\U0000FEFF';

u32_ifstream is(...);
char32_t bom;
is >> bom;
if(native_bom == bom)
{
  process_stream(is);
}
else
{
  basic_stringstream<char32_t> char_stream
  //Load the rest of `is` and endian-convert it into `char_stream`.
  process_stream(char_stream);
}
于 2018-05-02T18:36:40.617 回答
1

我目前感兴趣的是另一种欧洲语言,[so] ASCII 可能就足够了

不,即使是简单的英语。您知道 Microsoft Word 如何创建“弯引号”吗?这些是非ASCII字符。例如,所有带有重音符号和变音符号的字母。法语或英语是非 ASCII 字符。

我想在未来证明它

UTF-8、UTF-16 和 UTF-32 都可以编码每个 Unicode 代码点。它们都是面向未来的。UTF-32 与其他两个相比没有优势。

也为了未来的证明:我很确定某些脚本使用由多个代码点组成的字符(技术术语是“字素簇”)。粗略的搜索出现了玩弄梵文字符

UTF-32 的一个缺点是在其他工具中的支持。记事本不会打开您的文件。Beyond Compare 不会。Visual Studio 代码……不。Visual Studio 会,但不会让您创建此类文件。

还有 Win32 API:它有一个MultiByteToWideChar函数,可以将 UTF-8 转换为 UTF-16(您需要将其传递给所有 Win32 调用),但它不接受 UTF-32。

所以我对这个问题的诚实回答是,不要。否则按照尼科尔的回答。

于 2018-05-03T05:08:04.017 回答