在一位朋友的帮助下我有了以下理解,不一定全对但能够疏通他们之间的关系
Ansi
是一种规范定义1-128固定的全球统一的ANSI码表
然后各国在128 后面定义自己国家的文字
如:中
Ansi:D6D0
Ansi缺点各国编码有冲突没法通信 同样的编码在这个国家是这个字那个国家是那个字比如我们经常在国外下个代码回来打开一看
全都是乱码为了解决这个问题必须要统一所以有了
Unicode
【注意:是一种规范不是一种编码】
他定义了全球文字的代码点一共分为17组,他是无限可扩展的没有上限给每全球各国的字都字义一个索引
以后如果我们引入外星人文字也可以用Unicode向后扩展 打个比方哈哈!他只是规范不是编码
有了上面的规范那就可以定义编码了
Utf-16
这个就是真正的编码了代码点是2个字节的就用2字节表示 如果是3个字节的就用4字节表示 如果表示ANSI 1-128范围的就用1字节另一个字用00代替(这步就出现问题了下面说)
如:中
代码点:U+4E2D
Utf-16 :4E2D
Utf-8:E4B8AD
查编码范围 https://blog.csdn.net/qq_22520587/article/details/62454354
这个网站可以查编码 https://unicode-table.com/en/search/?q=中
Utf-8
另一种编码方式 他用1字节表示Ansi和Ansi一样的编码其它字用3字节表示包含目前全球所有文字
他的最大优势就是解决Utf-16说到的问题 Utf-8和Ansi一样在表示一个字符串时判断遇到00表示字符串就结束了
如果是Utf-16要用00 00才能判断出字符串结束了,所以Utf-8最大优势就是和Ansi兼容
在编程中我们可以直接用char *(Delphi 是PAnsiChar)指针 指向Utf-8的字符串 遇到00就是字符串结束的位置
如果是Utf-16 只能用wchar_t *(Delphi 是PWideChar)指向他 遇到 00 00 才是字符串结束符
我曾经错误的认识:
Windows API 中只要是涉及到字符串的API经常有两个版本 xxxxA xxxxW用最后A和W来区分
A是Ansi W经常说的就是这是Unicode【这里严格来说应该是Utf-16 Unicode只是规范不是编码Utf-16才是编码】
【Windows API中的W全都是Utf-16】
有关转换函数的正确理解
他的第一个参数
CP_ACP:ANSI代码页;
CP_MACCP:Macintosh代码页;
CP_OEMCP:OEM代码页;
CP_SYMBOL:符号代码页(42);
CP_THREAD_ACP:当前线程ANSI代码页;
CP_UTF7:使用UTF-7转换;
CP_UTF8:使用UTF-8转换。
常用的就只有两个 CP_ACP CP_UTF8
刚开始我不太明白这个到底指定的是输入参数还是输出参数
后来我看MSDN上函数的说明他是一个Utf-16的相互换转函数才明白
MultiByteToWideChar xxxx -> UTF-16
WideCharToMultiByte UTF-16 --> xxxx
就是说第一个参数其实是指定的那个xxxx的类型
函数互相转换这里就引用别人的出处
https://blog.csdn.net/bajianxiaofendui/article/details/83302855
std::wstring AnsiToUTF16(const std::string &strAnsi)
{
//获取转换所需的接收缓冲区大小
int nUnicodeLen = ::MultiByteToWideChar(CP_ACP, 0, strAnsi.c_str(), -1, NULL, 0);
//分配指定大小的内存
wchar_t* pUnicode = new wchar_t[nUnicodeLen + 1];
memset((void*)pUnicode, 0, (nUnicodeLen + 1) * sizeof(wchar_t));
//转换
::MultiByteToWideChar(CP_ACP, 0, strAnsi.c_str(), -1, (LPWSTR)pUnicode, nUnicodeLen);
std::wstring strUnicode;
strUnicode = (wchar_t*)pUnicode;
delete[]pUnicode;
return strUnicode;
}
std::string UTF16ToANSI(const std::wstring& strUnicode)
{
int nAnsiLen = WideCharToMultiByte(CP_ACP, 0, strUnicode.c_str(), -1, NULL, 0, NULL, NULL);
char *pAnsi = new char[nAnsiLen + 1];
memset((void*)pAnsi, 0, (nAnsiLen + 1) * sizeof(char));
::WideCharToMultiByte(CP_ACP, 0, strUnicode.c_str(), -1, pAnsi, nAnsiLen, NULL, NULL);
std::string strAnsi;
strAnsi = pAnsi;
delete[]pAnsi;
return strAnsi;
}
std::wstring UTF8ToUTF16(const std::string& str)
{
int nUnicodeLen = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
wchar_t* pUnicode;
pUnicode = new wchar_t[nUnicodeLen + 1];
memset((void*)pUnicode, 0, (nUnicodeLen + 1) * sizeof(wchar_t));
::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, (LPWSTR)pUnicode, nUnicodeLen);
std::wstring strUnicode;
strUnicode = (wchar_t*)pUnicode;
delete []pUnicode;
return strUnicode;
}
std::string UTF16ToUTF8(const std::wstring& strUnicode)
{
int nUtf8Length = WideCharToMultiByte(CP_UTF8, 0, strUnicode.c_str(), -1, NULL, 0, NULL, NULL);
char* pUtf8 = new char[nUtf8Length + 1];
memset((void*)pUtf8, 0, sizeof(char) * (nUtf8Length + 1));
::WideCharToMultiByte(CP_UTF8, 0, strUnicode.c_str(), -1, pUtf8, nUtf8Length, NULL, NULL);
std::string strUtf8;
strUtf8 = pUtf8;
delete[] pUtf8;
return strUtf8;
}
std::string AnsiToUtf8(const std::string &strAnsi)
{
std::wstring strUnicode = AnsiToUnicode(strAnsi);
return UnicodeToUTF8(strUnicode);
}
std::string Utf8ToAnsi(const std::string &strUtf8)
{
std::wstring strUnicode = UTF8ToUnicode(strUtf8);
return UnicodeToANSI(strUnicode);
}