C/C++ 中的跨平台 unicode:使用哪种编码?
Posted
技术标签:
【中文标题】C/C++ 中的跨平台 unicode:使用哪种编码?【英文标题】:Cross-platform unicode in C/C++: Which encoding to use? 【发布时间】:2012-06-29 11:49:23 【问题描述】:我目前正在从事一个爱好项目 (C/C++),它应该可以在 Windows 和 Linux 上运行,并且完全支持 Unicode。可悲的是,Windows 和 Linux 使用不同的编码使我们的生活更加困难。
在我的代码中,我尝试使用尽可能通用的数据,以便 Windows 和 Linux 都可以轻松使用。在 Windows 中,wchar_t 默认编码为 UTF-16,在 Linux 中为 UCS-4(如果我错了,请纠正我)。
我的软件打开(_wfopen、UTF-16、Windows、fopen、UTF-8、Linux)并将数据写入 UTF-8 格式的文件。到目前为止,这一切都是可行的。直到我决定使用 SQLite。
SQLite 的 C/C++ 接口允许一个或两个字节的编码字符串 (click)。 当然这不适用于 Linux 中的 wchar_t,因为 Linux 中的 wchar_t 默认为 4 个字节。因此,sqlite的读写需要在Linux下进行转换。
目前,代码因 Windows/Linux 的异常而杂乱无章。我希望坚持在 wchar_t 中存储数据的标准理念:
Windows 中的 wchar_t:文件路径没有问题,读取/写入 sqlite 没有问题。无论如何,都应该以 UTF-8 将数据写入文件。 Linux 中的 wchar_t:由于 UTF-8 编码、读取/写入到 sqlite (wchar_t) 之前的转换以及将数据写入文件时的 windows 相同,文件路径例外。在阅读 (here) 之后,我确信我应该在 Windows 中坚持使用 wchar_t。但在完成所有这些工作之后,问题就从移植到 Linux 开始了。
目前我正在考虑重做这一切以坚持使用简单的 char(UTF-8),因为它适用于 Windows 和 Linux,请记住我需要在 Windows 中为每个字符串“WideCharToMultiByte”以实现 UTF -8。使用简单的基于 char* 的字符串将大大减少 Linux/Windows 的异常数量。
您有跨平台使用 unicode 的经验吗?关于简单地将数据存储在 UTF-8 中而不是使用 wchar_t 的想法有什么想法吗?
【问题讨论】:
2byte 字符编码绝对是不是 UTF-16。 UTF-16 是 2 到 4 个字节,而 UTF-8 是 1 - 4 个字节。 Windowswchar_t
不是 UTF-16,它是 UCS2。实际上,您可能不会注意到差异,因为 UCS2 涵盖了 BMP,但如果您的用户决定他们必须在 Ogham 或符文中拥有数据...
Windows 使用 UTF-16,并且使用 wchar_t
来保存 UTF-16 数据,并且从 Windows 2000 开始就一直这样做。
关于 wchar_t 的用途和用途:***.com/a/11107667/365496
@RemyLebeau:我认为这取决于上下文。例如,您可以设置一个无效的 Unicode 密码,而控制台函数(例如 WriteConsoleOutputCharacter)似乎只允许在每个控制台坐标处使用一个 16 位字(可能解释为 UCS2)。
utf8everywhere.org 几乎可以在网站的 URL 中回答这个问题 :)
【参考方案1】:
我们的软件也是跨平台的,我们也面临类似的问题。我们决定我们的目标是尽可能减少转化次数。这意味着我们在 Windows 上使用wchar_t
,在 Unix/Mac 上使用char
。
我们通过在 Unix 上支持 _T
和 LPCTSTR
以及类似的功能以及在 std::string
和 std::wstring
之间轻松转换的通用函数来做到这一点。我们还有一个在大多数情况下使用的通用std::basic_string<TCHAR>
(tstring
)。
到目前为止,这工作得很好。基本上大多数函数采用tstring
或LPCTSTR
,而那些不采用的函数将从tstring
转换其参数。这意味着大多数时候我们不会转换字符串并传递大多数参数。
【讨论】:
这也是一个可能的解决方案,但仍然有点 hacky。此外,从我的阅读中我了解到,我应该避免使用 TCHAR,因为它是为了通过切换到 MBCS 而不是 Unicode 标志来支持与旧软件的向后兼容性而引入的。 @Fozi,如何在 Ubuntu Linux 上支持 _T?非常感谢。 @ErikKou,在 Unix 或 Linux 中模拟 Windows 宏 _T 的可能解决方案是什么?谢谢。【参考方案2】:所有平台上的 UTF-8,在 Windows 上即时转换为 UTF-16 是跨平台 Unicode 的常用策略。
【讨论】:
我会稍微调整一下该声明并说:所有平台上的本机编码,与 UTF-8 之间的即时转换。每当字符串离开应用程序(例如写入文件、通过网络套接字发送数据、将输入传递到库等)时,都需要进行即时转换。当然,这一切都取决于具体的场景。 Unicode,更具体地说是 UTF-8,是人类最优雅、最令人印象深刻的创造和社会制度之一。在 UTF-8 成为标准之后开始开发,我感到非常幸运。以上是关于C/C++ 中的跨平台 unicode:使用哪种编码?的主要内容,如果未能解决你的问题,请参考以下文章