最近遇到中文路徑訪問的問題,又重新學習了一遍ansi與Unicode的知識,博文記錄下來以供后續參考。
ANSI 編碼
ANSI是一種字符代碼,為使計算機支持更多語 言,通常使用0x80~0xFF 范圍的2 個字節來表示1 個字符。不同的國家和地區制定了不同的標准,由此產生了GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的編碼標准。 這些使用多個字節來代表一個字符的各種漢字延伸編碼方式,稱為ANSI 編碼。
關於MBCS字符集(Multi Byte Character System):GB2312、GBK等編碼被稱為MBCS,MBCS同ASCII是完全兼容的。對於前ASCII的128個字符,在MBCS字符集下有完全相同的編碼,而漢字等字符用多個字節存儲。也意味着MBCS下,字符的長度有可能有1個字節的,也有多個字節的。
所以ANSI編碼其實是一個統稱,不同的語言使用不同的編碼規范,並沒有跨語言統一編碼。比如 windows7 notepad記事本保存的時候,在彈出對話框的下方有“編碼”下拉框,默認是“ANSI”,也可以選擇“Unicode”(其實是UTF-16)和 “UTF-8”。如果選擇了ANSI,那么實際使用的編碼規范就跟你的操作系統版本強相關了,如果是簡體中文的windows就會用GBK標准。
Unicode編碼
就是把地球上所有的語言的符號,都用統一的字符集來表示,一個編碼真正做到了唯一。Unicode只是確定了字符的二進制編碼,但並沒有確定字符存儲的具體實現方式。比如UTF-8 ,UTF16是常見的Unicode實現方式。
UTF-16編碼的字符,要么是2個字節,要么是4個字節表示的。windows2000以上版本使用UTF-16,老版本windows用的ANSI。
ANSI字符串轉Unicode(windows下對應UTF-16編碼)
在vc工程選擇unicode編譯的情況下,如果是字符串常量可以直接使用L和_T or _TEXT宏,也可以使用wsprintf函數進行轉換(需要引用Windows.h)。
// all strings are Unicode
swprintf(szW,L " %s ",L " Unicode Str中文 ");
CString name = _T( " Report.txt ");
// ANSI to Unicode,wsprintf可以直接用,使用大寫的%S
// 注意swprintf函數是不行的,據說要先加setlocale(LC_CTYPE, "chs")語句
wsprintfW(szW,L " %S ", " Unicode Str中文 ");
// 獲取工作目錄的路徑,ANSI編碼,路徑中的中文字符占用2個字節
std:: string s_currPath = _getcwd(buff, 512);
TCHAR szW[ 512];
USES_CONVERSION;
// 注意使用A2W宏,不可直接調用swprintf_s(szW,512,L"%S",...)
swprintf_s(szW, 512,L " %s ",A2W(s_currPath.c_str()));
// wsprintf可以直接使用
wsprintfW(szW,L " %S ",s_currPath.c_str());
和上面類似,使用ATL的宏W2A即可。或者使用wsprintfA(sA, "%S", L"中文"),其中sA是char數組。
另外,轉換還可以使用功能更強大的WideCharToMultiByte函數和MultiByteToWideChar函數。