我有一个带有utf8实体的字符串(我不确定我是否正确命名):
std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441";
我怎么能把它转换成更具可读性的东西?我使用g ++和C ++ 11支持,但经过几个小时的挖掘std :: codecvt手册我得不到结果:
std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441";
wstring_convert<codecvt_utf8_utf16<char16_t>,char16_t> convert;
string dest = convert.to_bytes(std);
返回以:
开头的梦魇堆栈跟踪error: no matching function for call to ‘std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>::to_bytes(std::string&)
我希望还有另一种方式。
答案 0 :(得分:2)
首先,您对std::wstring_convert
的使用是倒退的。您有一个UTF-8编码std::string
,您想要转换为宽Unicode字符串。您收到编译器错误,因为to_bytes()
未将std::string
作为输入。它需要std::wstring_convert::wide_string
作为输入(在您的情况下为std::u16string
,因为您在专业化中使用了char16_t
,因此您需要使用from_bytes()
代替{ {1}}:
to_bytes()
现在,正如所说,JSON specification州的第9节:
9 String
字符串是用引号(U + 0022)包装的Unicode代码点序列。除了必须转义的字符外,所有字符都可以放在引号内:引号(U + 0022),反向固相(U + 005C)和控制字符U + 0000到U + 001F。某些字符有两个字符的转义序列表示。
std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441"; std::wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t> convert; std::u16string dest = convert.from_bytes(std);
表示引号字符(U + 0022)。
\"
表示反向固相字符(U + 005C)。
\\
表示固相字符(U + 002F)。
\/
代表退格字符(U + 0008)。
\b
表示换页符(U + 000C)。
\f
代表换行符(U + 000A)。
\n
表示回车符(U + 000D)。
\r
表示字符制表符(U + 0009)。因此,例如,只包含一个反向固相字符的字符串可以表示为&#34;
\t
&#34;。任何代码点都可以表示为十六进制数。这个数字的含义由ISO / IEC 10646确定。如果代码点在基本多语言平面(U + 0000到U + FFFF)中,那么它可以表示为六个字符的序列:a反向实线,后跟小写字母
\\
,后跟四个编码代码点的十六进制数字。十六进制数字可以是数字(U + 0030到U + 0039)或十六进制字母u
到A
大写(U + 0041到U + 0046)或小写(U + 0061到U + 0066) )。因此,例如,仅包含单个反向固相字符的字符串可以表示为&#34;F
&#34;。以下四个案例都产生相同的结果:
&#34;
\u005C
&#34;&#34;
\u002F
&#34;&#34;
\u002f
&#34;&#34;
\/
&#34;要转义不在基本多语种平面中的代码点,该字符将表示为十二个字符的序列,编码UTF-16代理项。因此,例如,仅包含G谱号字符(U + 1D11E)的字符串可以表示为&#34;
/
&#34;。
原始JSON数据本身可以用UTF-8(最常见的编码),UTF-16等编码。但无论使用何种编码,字符序列\uD834\uDD1E
代表UTF-16代码序列"\u0418\u043d\u0434\u0435\u043a\u0441"
,这是Unicode字符串U+0418 U+043d U+0434 U+0435 U+043a U+0441
。
如果您使用实际的JSON解析器(例如JSON for Modern C++,jsoncpp,RapidJSON等),它将为您解析UTF-16 codeunit值并返回可读的Unicode字符串
但是,如果您手动处理JSON数据,则必须手动解码任何"Индекс"
和\x
转义序列。 \uXXXX
无法为您做到这一点。它只能将JSON从std::wstring_convert
转换为std::string
/ std::wstring
,如果这样可以更轻松地解析数据。但是,您仍然需要单独解析JSON的内容。
之后,如果需要,您可以使用std:::u16string
将任何提取的std::wstring_convert
/ std::wstring
字符串转换回UTF-8以节省内存。
答案 1 :(得分:0)
您看到的不是实体,而是代码点。您通过Unicode转义序列定义字符,编译器会自动将它们转换为UTF-8。将其转换为UTF-16的典型方法,反之亦然:
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string ws2s(const std::wstring &wstr) {
std::string narrow = converter.to_bytes(wstr);
return narrow;
}
std::wstring s2ws(const std::string &str) {
std::wstring wide = converter.from_bytes(str);
return wide;
}
当然,您无法将原始字符串转换为另一个相同类型的字符串(std :: string),因为它无法容纳此类字符。这就是编译器首先将UTF-16代码转换为UTF-8的原因。