C ++读写UTF-32文件

时间:2018-05-02 17:04:46

标签: c++ winapi unicode windows-10 utf-32

我想使用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的一部分,或者通常随该操作系统一起提供。

2 个答案:

答案 0 :(得分:1)

如果您有char32_t序列,则可以使用std::basic_ofstream<char32_t>将其写入文件(我将其称为u32_ofstream,但此typedef不存在)。这与std::ofstream完全相同,只是它写char32_t而不是char s。但是有一些限制。

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

但是你要面对的重大问题是端序问题。 u32_ofstream会将char32_t写为您平台的原生端。如果您的应用程序通过u32_ifstream将其读回,那很好。但是,如果其他应用程序读取它们,或者您的应用程序需要读取其他人用UTF-32编写的内容,则会出现问题。

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

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

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

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);
}

答案 1 :(得分:1)

  

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

没有。即使是简单的英语。你知道Microsoft Word如何创建“卷曲引号”吗?那些是非ASCII字符。所有那些带有重音符号和变音符号的字母例如。法语或英语是非ASCII字符。

  

我想将来证明它

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

同样适用于未来的校对:我非常确定某些脚本使用由多个代码点组成的字符(技术术语是'字形集群')。粗略搜索出现Playing around with Devanagari characters

UTF-32的缺点是其他工具的支持。记事本不会打开您的文件。超越比较不会。 Visual Studio Code ...不。 Visual Studio会,但它不会让你创建这样的文件。

Win32 API:它有一个函数MultiByteToWideChar ,它可以将UTF-8转换为UTF-16(你需要传入所有Win32调用),但它不接受UTF-32。 / p>

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