在Linux中将std :: string转换为Unicode

编辑我意识到这是错误的开始后修改了问题。

我正在将一个C#应用程序的一部分移植到Linux,在那里我需要得到一个UTF-16string的字节:

string myString = "ABC"; byte[] bytes = Encoding.Unicode.GetBytes(myString); 

所以bytes数组现在是:

 "65 00 66 00 67 00" (bytes) 

我怎样才能在Linux上实现相同的C + +? 我有一个定义为std::stringmyString ,似乎Linux上的std::wstring是4个字节?

最简单的方法是抓住一个小型图书馆,如UTF8 CPP ,做一些事情:

 utf8::utf8to16(line.begin(), line.end(), back_inserter(utf16line)); 

你的问题不是很清楚,但我会尽力澄清一些困惑。

介绍

在C标准的'95修正案之后,C中字符集的处理状态(并且由C ++继承)。

  • 所使用的字符集由当前语言环境给出

  • wchar_t是为了存储代码点

  • char是为了存储一个多字节编码的形式(一个约束,例如,基本字符集中的字符必须编码在一个字节)

  • 字符串文字以实现定义的方式进行编码。 如果他们使用基本字符集之外的字符,则不能认为它们在所有语言环境中都是有效的。

因此,使用16位wchar_t您只能使用BMP。 使用UTF-16的替代品是不合规的,但我认为MS和IBM或多或少被迫这样做,因为他们认为Unicode将永远是一个16位的字符集。 那些延迟Unicode支持的人倾向于使用32位wchar_t。

较新的标准不会有太大的改变。 UTF-8,UTF-16和UTF-32编码的字符串大部分都是字面值,并且有16位和32位字符的类型。 标准库中的Unicode很少或没有额外的支持。

如何做一个编码到另一个的转换

你必须在使用Unicode的语言环境中。 希望

 std::locale::global(locale("")); 

就足够了。 如果没有,您的环境没有正确设置(或设置为另一个字符集,并假设Unicode将不会为您的用户提供服务)。

C风格

使用wcstomsbwcstomsb函数。 这是你问的一个例子。

 std::string narrow(std::wstring const& s) { std::vector<char> result(4*s.size() + 1); size_t used = wcstomsb(&result[0], s.data(), result.size()); assert(used < result.size()); return result.data(); } 

C ++风格

语言环境的codecvt方面提供所需的功能。 好处是你不必改变使用它的全局语言环境。 不方便的是使用更复杂。

 #include <locale> #include <iostream> #include <string> #include <vector> #include <assert.h> #include <iomanip> std::string narrow(std::wstring const& s, std::locale loc = std::locale()) { std::vector<char> result(4*s.size() + 1); wchar_t const* fromNext; char* toNext; mbstate_t state = {0}; std::codecvt_base::result convResult = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(loc) .out(state,&s[0], &s[s.size()], fromNext, &result[0], &result[result.size()], toNext); assert(fromNext == &s[s.size()]); assert(toNext != &result[result.size()]); assert(convResult == std::codecvt_base::ok); *toNext = '\0'; return &result[0]; } std::wstring widen(std::string const& s, std::locale loc = std::locale()) { std::vector<wchar_t> result(s.size() + 1); char const* fromNext; wchar_t* toNext; mbstate_t state = {0}; std::codecvt_base::result convResult = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(loc) .in(state, &s[0], &s[s.size()], fromNext, &result[0], &result[result.size()], toNext); assert(fromNext == &s[s.size()]); assert(toNext != &result[result.size()]); assert(convResult == std::codecvt_base::ok); *toNext = L'\0'; return &result[0]; } 

你应该通过更好的处理来替换断言。

顺便说一句,这是标准的C ++,并不假定Unicode除了计算结果的大小,你可以通过检查可以指示部分转换convResult更好)。

我通常使用Poco C ++库中的UnicodeConverter类。 如果你不想要依赖,那么你可以看看代码。