C++ 如何使STL std::string在windows上与unicode一起工作?

C++ 如何使STL std::string在windows上与unicode一起工作?,c++,windows,string,unicode,stl,C++,Windows,String,Unicode,Stl,在我的公司,我们有一个跨平台(Linux和Windows)库,其中包含我们自己对STL std::string的扩展,这个类在字符串之上提供了所有种类的功能;拆分、格式化、到/从base64等。最近,我们被要求使这个字符串unicode“友好”,基本上它需要支持中文、日文、阿拉伯文等字符。经过初步研究,这在Linux端似乎很好,因为每件事本身都是UTF-8,但我在Windows端遇到了麻烦;让STL std::string在windows上作为UTF-8工作有什么诀窍吗?有可能吗?有更好的办法吗

在我的公司,我们有一个跨平台(Linux和Windows)库,其中包含我们自己对STL std::string的扩展,这个类在字符串之上提供了所有种类的功能;拆分、格式化、到/从base64等。最近,我们被要求使这个字符串unicode“友好”,基本上它需要支持中文、日文、阿拉伯文等字符。经过初步研究,这在Linux端似乎很好,因为每件事本身都是UTF-8,但我在Windows端遇到了麻烦;让STL std::string在windows上作为UTF-8工作有什么诀窍吗?有可能吗?有更好的办法吗?理想情况下,我们将基于std::string,因为这是Linux中string类的基础


谢谢,

您看过
std::wstring
了吗?它是
std::basic_string
的一个版本,用于
wchar\u t
,而不是
std::string
使用的
char

将UTF-8代码点放入
std::string
应该可以,无论平台如何。Windows上的问题是,几乎没有其他任何东西需要UTF-8,也没有任何东西需要UTF-8,而是需要UTF-16。您可以切换到存储UTF-16(至少在大多数Windows编译器上)的
std::wstring
,也可以编写其他接受UTF-8的例程(可能通过转换为UTF-16,然后传递到操作系统)。

在您的问题中存在一些误解

    < C++ > STL处理不存在编码。

  • std::string
    本质上是一个字节字符串,而不是字符字符串。因此,在其中填充UTF-8编码的Unicode应该没有问题。但是,请记住,所有
    string
    函数也可以处理字节,因此
    myString.length()
    将给出字节数,而不是字符数

  • Linux并不是天生的UTF-8。现在大多数发行版默认为UTF-8,但不应依赖它


不,没有办法让Windows将“窄”字符串视为UTF-8

以下是在这种情况下最适合我的方法(具有Windows和Linux版本的跨平台应用程序)

  • 在代码的跨平台部分使用std::string。假设它始终包含UTF-8字符串
  • 在代码的Windows部分,显式使用Windows API的“广泛”版本,即编写例如CreateFileW而不是CreateFile。这允许避免依赖于构建系统配置
  • 在platfrom抽象层中,根据需要在UTF-8和UTF-16之间进行转换(MultiByteToWideChart/WideCharToMultiByte)
我尝试过但不太喜欢的其他方法:

  • typedef std::basic_string tstring
    然后在业务代码中使用tstring。可以使用包装器/重载来简化std::string和std::tstring之间的转换,但这仍然会增加很多麻烦
  • 在任何地方使用
    std::wstring
    。由于Windows上的
    wchar\u t
    是16位的,因此没有多大帮助,因此您必须限制自己使用BMP,或者进行大量复杂操作,以使代码能够跨平台处理Unicode。在后一种情况下,UTF-8的所有好处都消失了
  • 在特定部分的平台中使用ATL/WTL/MFC
    CString
    ;在跨平台部分中使用
    std::string
    。这实际上是我上面推荐的一个变体
    CString
    在许多方面优于
    std::string
    (在我看来)。但它引入了额外的依赖性,因此并不总是可以接受或方便

如果您想避免头痛,请不要使用STL字符串类型。C++对Unicode或编码一无所知,因此为了便于携带,最好使用一个专门用于Unicode支持的库,例如ICU库。ICU默认使用UTF-16字符串,因此不需要转换,并且支持转换到许多其他重要编码,如UTF-8。还可以尝试使用跨平台库(如Boost.Filesystem)进行路径操作(
Boost::wpath
)。避免
std::string
std::fstream

在Windows API和C运行时库中,
char*
参数被解释为在“ANSI”代码页中编码。问题在于,这一点

我处于类似的情况,正处于从Windows到Linux移植软件的过程中,同时也使其成为Unicode意识。我们为此采取的方法是:

  • 使用UTF-8作为字符串的默认编码
  • 在特定于Windows的代码中,始终调用函数的“W”版本,根据需要在UTF-8和UTF-16之间转换字符串参数

这也是。

是-通过更加了解地区和编码

Windows对所有需要文本的内容都有两个函数调用,一个FoobarA()和一个FoobarW()。*W()函数接受UTF-16编码的字符串,*A()接受当前代码页中的字符串。但是,Windows不支持UTF-8代码页,因此您不能直接将其用于*a()函数,也不希望依赖用户设置。如果希望在Windows中使用“Unicode”,请使用支持Unicode(*W)的函数。有很多教程,通过谷歌搜索“Unicode Windows教程”应该可以得到一些

如果将UTF-8数据存储在std::字符串中,那么在将其传递给Windows之前,请将其转换为UTF-16(Windows提供了执行此操作的函数),然后将其传递给Windows

其中许多问题都是由于C/C++通常是编码不可知的
char
不是真正的字符,它只是一种整数类型。即使使用
char
数组来存储UTF-8数据,如果需要访问单个代码单元,也会给您带来麻烦,因为标准没有定义
char
的有符号性。州议会
std::string _old = u8"D:\\Folder\\This \xe2\x80\x93 by ABC.txt"s;
std::string _old = u8"D:\\Folder\\This \xe2\x80\x93 by ABC.txt";
std::cout << _old.data();