在我的应用程序中,由于不同的API(boost,win32,ffmpeg等等),我必须不断地在std::string
和std::wstring
之间转换字符串。特别是对于ffmpeg,字符串最终为utf8-> utf16-> utf8-> utf16,只是为了打开文件。
由于UTF8向后兼容ASCII,我认为我一直存储所有字符串UTF-8 std::string
,并且只有在必须调用某些异常函数时才转换为std::wstring
。
这很好用,我为utf8实现了to_lower,to_upper,iequals。然而,我遇到了几个死胡同std :: regex,以及常规的字符串比较。为了使这个可用,我需要实现一个基于std :: string的自定义ustring
类,并重新实现所有相应的算法(包括正则表达式)。
基本上我的结论是utf8对于一般用法并不是很好。当前的std::string/std::wstring
很糟糕。
但是,我的问题是为什么默认std::string
和""
不会简单地更改为使用UTF8?特别是因为UTF8向后兼容?可能有一些编译器标志可以做到这一点吗?当然,需要自动调整stl实现。
我看过ICU,但是假设使用basic_string,它与apis不兼容,例如没有开始/结束/ c_str等...
答案 0 :(得分:8)
主要问题是内存表示和编码的混合。
任何Unicode编码都不适合文本处理。用户通常会关注字形(屏幕上的内容),而编码是根据代码点定义的......有些字形由几个代码点组成。
因此,当有人问:"Hélène"
(法语名字)的第5个字符是什么时,这个问题很混乱:
n
。é
和è
的表示(它们可以表示为单个代码点或使用变音符号表示对...)< / LI>
根据问题的来源(屏幕前的最终用户或编码例程),响应完全不同。
因此,我认为真正的问题是为什么我们在这里谈论编码?
今天它没有意义,我们需要两个“观点”:字形和代码点。
不幸的是,std::string
和std::wstring
接口是从人们认为ASCII足够的时候继承的,并且所取得的进展并没有真正解决问题。
我甚至不理解为什么应该指定内存中表示,它是一个实现细节。用户应该想要的是:
......谁在乎它的代表?我认为好的软件建立在封装上?
嗯,C关心,我们想要互操作性......所以我猜它会在C时修复。
答案 1 :(得分:3)
你不能,其主要原因是 Microsoft 。他们决定不支持Unicode作为UTF-8,因此在Windows下对UTF-8的支持很少。
在Windows下,您无法使用UTF-8作为代码页,但您可以从UTF-8转换为UTF-8。
答案 2 :(得分:3)
在Windows上使用UTF8有两个障碍。
你不知道一个字符串将占用多少字节 - 它取决于存在哪些字符,因为有些字符占用1个字节,有些占用2个,有些占用3个,有些占用4个。
< / LI>Windows API使用UTF16。由于大多数Windows程序会对Windows API进行大量调用,因此前后转换的开销很大。 (请注意,您可以执行&#34;非unicode&#39; build,看起来它使用的是utf8 windows api,但所有发生的事情都是隐藏每次调用的前后转换)
UTF16的一大障碍是字符串的二进制表示取决于程序运行的特定硬件上的字中的字节顺序。在大多数情况下,这并不重要,除非在计算机之间传输字符串,而您无法确定其他计算机是否使用相同的字节顺序。
那该怎么办?我在任何地方使用UTF16&#39;内部&#39;我所有的节目。当字符串数据必须存储在文件中或从套接字传输时,我首先将其转换为UTF8。
这意味着95%的代码运行简单且效率最高,UTF8和UTF16之间的所有混乱转换都可以隔离到负责I / O的例程。