研究Hprose的windows编译时,发现它使用了emoji编码。emoji需要utf-32的字符才能存下。(此句不准确,应该是至少4个字节才能存放)。所以有说法用mysql存emoji时,需要使用utf8-mb4。
比如:??
首先来个简单的测试程序:
g++-6 -std=c++11 encoding.cpp -o encoding
#include #include #include
using namespace std;
int main()
{
printf("sizeof(wchar_t)=%zu\n", sizeof(wchar_t));
printf("sizeof(char16_t)=%zu\n", sizeof(char16_t));
printf("sizeof(char32_t)=%zu\n", sizeof(char32_t));
const char native[] = "??";
printf("native:");
for (unsigned i = 0; i < strlen(native); i++)
{
printf("%02x ", (unsigned char)native[i]);
}
printf("\n");
wchar_t wchar[] = L"??";
printf("wchar:");
for (auto item : wchar)
{
printf("%x ", item);
}
printf("\n");
wstring wstr = L"??";
printf("wstr:");
for (auto item : wstr)
{
printf("%x ", item);
}
printf("\n");
u16string u16str = u"??";
printf("u16:");
for (auto item : u16str)
{
printf("%x ", item);
}
printf("\n");
u32string u32str = U"??";
printf("u32:");
for (auto item : u32str)
{
printf("%x ", item);
}
printf("\n");
return 0;
}
Linux上输出:
sizeof(wchar_t)=4
sizeof(char16_t)=2
sizeof(char32_t)=4
native:f0 9f 87 a8 f0 9f 87 b3
wchar:1f1e8 1f1f3 0
wstr:1f1e8 1f1f3
u16:d83c dde8 d83c ddf3
u32:1f1e8 1f1f3
(1)其对应的utf32(u32string)为:1f1e8 1f1f3
(2)其对应的utf8(string)为:f0 9f 87 a8, f0 9f 87 b3
-> 11110[000] 10[0011111] 10[000111] 10[101000],即000001 11110001 11101000=0x1f1e8
和 11110[000] 10[0011111] 10[000111] 10[110011],即000001 11110001 11110011=0x1f1f3
和utf32匹配了。
(3)其对应的utf16(u16string)为:d83c dde8 d83c ddf3
-> 1101 10[00 0011 1100], 1101 11[01 1110 1000],即000[0+1] 11110001 11101000=0x1f1e8
和 1101 10[00 0011 1100], 1101 11[01 1111 0011],即000[0+1] 11110001 11110011=0x1f1f3
和utf32也是匹配的。注意计算中要加1。
(4)其对应的Windows的wstring是d83c dde8 d83c ddf3。
转码得到的是:ED A0 BC, ED B7 A8, ED A0 BC, ED B7 B3
ED A0 BC 1110 [1101] 10[10 0000] 10[11 1100] 即 1101 1000 0011 1100 -> D8 3C
ED B7 A8 1110 [1101] 10[11 0111] 10[10 1000] 即 1101 1101 1110 1000 -> DD E8
ED A0 BC 1110 [1101] 10[10 0000] 10[11 1100] 即 1101 1000 0011 1100 -> D8 3C
ED B7 B3 1110 [1101] 10[11 0111] 10[11 0011] 即 1101 1101 1111 0011 -> DD F3
参考
Facet 说明
std::codecvt_utf8 封装了UTF-8与UCS2及UTF-8与UCS4的编码转换
std::codecvt_utf16 封装了UTF-16与UCS2及UTF-16与UCS4的编码转换
std::codecvt_utf8_utf16 封装了UTF-8与UTF-16的编码转换
说明hprose使用
std::wstring_convert<:codecvt_utf8>> conv;
writeString(conv.to_bytes(str));
对于windows产生的是UCS2->UTF8,对于linux/mac产生的是UTF32->UTF8。
std::wstring_convert<:codecvt_utf8_utf16>, wchar_t> conv;
writeString(conv.to_bytes(str));
产生的是UTF16->UTF8。