C++读取和写入 UTF-32 文件
C++ read and write UTF-32 files
我想使用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 的一部分或通常随该操作系统一起提供。
如果你有一个char32_t
序列,你可以使用std::basic_ofstream<char32_t>
将其写入文件(我称之为u32_ofstream
,但这个typedef不存在(。这和std::ofstream
完全一样,只是它写的是char32_t
s而不是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,那么您可以正常读取文件的其余部分。如果没有,则需要先读取文件并对其进行字节序转换,然后才能对其进行处理。该过程看起来有点像这样:
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);
}
我目前感兴趣的是另一种欧洲语言,[所以] ASCII 可能就足够了
不。即使是简单的英语。你知道Microsoft Word 是如何创建"卷曲引号"的吗?这些是非 ASCII 字符。所有那些带有重音和变音符号的字母,例如。法语或英语是非 ASCII 字符。
我想让它面向未来
UTF-8、UTF-16 和 UTF-32 都可以对每个 Unicode 码位进行编码。它们都是面向未来的。UTF-32 与其他两个相比没有优势。
同样为了将来证明:我很确定某些脚本使用由多个代码点组成的字符(技术术语是"字素簇"(。粗略搜索一下,就会发现"玩弄梵文"字符。
UTF-32 的一个缺点是支持其他工具。记事本无法打开您的文件。超越比较不会。Visual Studio Code...不。Visual Studio会,但它不会让你创建这样的文件。
还有Win32 API:它有一个函数MultiByteToWideChar,可以将UTF-8转换为UTF-16(你需要传递给所有Win32调用(,但它不接受UTF-32。
所以我对这个问题的诚实回答是,不要。否则,请遵循尼科尔的回答。
- 如何将 UTF-8 文本从文件转换为某个可以迭代的容器,并检查每个符号是否为C++字母数字?
- C++读取和写入 UTF-32 文件
- 在这种情况下,UTF-16 和 UTF-32 的 BOM 是强制性的
- 在 Linux 中将 UTF-32 宽字符转换为 UTF-16 宽字符以获取补充平面字符
- cpp 预处理器无法识别 UTF-32 字符串
- 跨平台UTF-8字符文件数据编码/解码
- 如何使Windows 7支持12000(UTF-32)代码页或1200(UTF-16)代码页
- 将 UTF-8 转换为 UTF-32,预先计算每个'chars'数
- 需要说明如何使用 C++ 在 Linux 上创建 utf-8 编码文件
- std::wstring在Windows上支持UTF-16和UTF-32吗
- 使用ICU(ICU4C)读取UTF-8编码文件的缓冲区大小
- 在C++内部使用UTF-8与UTF-16与UTF-32
- Linux控制台的国际UTF-32字符串输出
- 哪些开源C或c++库可以将任意UTF-32转换为NFC
- 读取Unicode UTF-32文件到wstring
- c++是否支持除UTF-8、UTF-16和UTF-32以外的字符编码之间的转换?
- 将UTF-32字符打印到终端
- 如何在Linux上使用std库从utf-16转换为utf-32
- 在使用STL的迭代器上使用UTF-8到UTF-32
- 如何使用wfstream将UTF-16文件读取到wstring中