在一位朋友的幫助下我有了以下理解,不一定全對但能夠疏通他們之間的關係
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://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);
}