一 、背景知識
? 1、計算機中所有的數據都用01串來表示,至于一串01到底代表什么是由軟件來設定的。
??? 比如:01111101111101010111110111110101??? 可以理解為一條指令,也可以理解為4個字節的char字符,具體是什么要看這個數據是在代碼段還是數據段。
? 2、字符是人看到的顯示效果(實際上人看到的是字符對應glyph渲染到屏幕上的效果)
? 3、字符有內部的存儲格式(如'中' 在內存中存為 d6d0(gb2312編碼)),這種編碼叫內碼,本質上是將人理解的字符,映射為二進制01串
? 4、字符需要在系統間交換,這時同樣是'中'在簡體中文版OS和繁體中文版OS中內部表示的格式不同,為了進行數據交換,需要能夠標記一個字符,這種編碼叫交換碼,典型的如 unicode、CNS 11643、CCCII
? 5、windows NT一個字符顯示的過程:讀入內碼---轉為unicode(wide char)---找到字體中對應的字模(glyph)---將此glyph(位圖)寫到顯存---調用顯卡刷到顯示器上
二、基本概念
? 1、計算機一開始是在英語國家中產生的,所以計算機的系統一開始都會做一件事:對拉丁字母進行編碼,加上一些控制符號、數學符號等,這便形成了ASCII編碼。
? 2、像英語這樣的拼音文字很容易編碼,因為所有的詞是由26個字母組合而成的,只要編碼26個字母,就可以輸入所有的單詞。但是像中文這樣的象形文字,則只能針對每個字分別進行編碼(因為每個字的字形都不一樣),這樣舊有的編碼是沒法滿足中國人的要求的(你總不能要求只有懂英語的人才能用電腦吧!), 所以老一代的中國程序員就要為中文進行編碼,其中典型的代表是gb2312(簡體)、big5(繁體),所謂的編碼就是確定中文的每個字在內存中對應的01串是什么,比如'國'在內存中用 b9fa(gb2312編碼)表示。
? 3、因為每個國家的文字是不同的,編碼的方式也是不同的,比如b9fa在大陸代表 '國', 在日本就代表特定的日語字符了,那么怎么樣進行信息交換呢?比如我在中國寫了一份源代碼,現在要拿到日本編譯,那么不好意思,編譯不了,因為這里的語義已經改變了。為了能夠進行信息的交換,最簡單的辦法就是為全世界所有的語言的所有的字符都指定一個唯一的編碼,這個就是unicode編碼
? 4、unicode是統一標記,但是unicode有很多種內部存儲的格式,比如unicode為4e2d的字符在內存中可以用3、4或5個字節來表示,這種內部存儲的表示形式叫內碼,典型的實現有utf-8(unix標準)、utf-16(windows標準)、utf-32等
? 5、在簡體中文windows下使用文本編輯器創建的文本文件,使用的編碼方式是gb2312,即編碼方式是根據locale確定的默認的編碼方式。如果需要和類unix系統下的人進行協作開發時就要注意將編碼方式改為utf-8
三、編碼轉換
? 2種內碼進行轉換,需要有個媒介------unicode,一個轉換編碼的例子:(windows平臺) uft8(multibyte)------unicode(wideChar)-----gb2312(multibyte)
int UTF8ToGB(const char* str,char *out)
{
? WCHAR *strSrc;
? TCHAR *szRes;
? int len;
? //獲得臨時變量的大小
? // 后4個參數是輸入的指針,長度,輸出的指針,長度,這里第4個參數是-1,返回unicode字符數
? int i = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
? strSrc = new WCHAR[i+1];// unicode 字符數組
? MultiByteToWideChar(CP_UTF8, 0, str, -1, strSrc, i);
? //獲得臨時變量的大小
? i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
? szRes = new TCHAR[i+1];// 內碼字符的長度
? WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);
? len = (i+1)*sizeof(CHAR);
? memcpy(out,szRes,len);
? out[len+1] ='\0';
? delete []strSrc;
? delete []szRes;
? return len;
}
四、編程語言的支持
1、java? java內置對unicode的支持,即 new String(...) 時,使用的是unicode編碼格式,所有字符串的操作也是針對unicode,要返回指定編碼的字節數組使用getBytes
例子:
2、c、c++
char VS wchar? string VS wstring
例子: vc2005測試
// testString.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <cstring>
#include <iostream>
#include <string>
#include <locale>
int main(int argc, char* argv[])
{
? const char text[] = "中\u534e人民共和國,龢籦" ;??????????????????? // 這個里面存的是字符串的gb2312內碼,但是可以用\u(unicode)來指定字符
? const wchar_t wtext[] = L"中\u534e人民共和國,龢籦" ;?????????????? // 這個里面存的是unicode
? std::string s1("中\u534e人民共和國,龢籦" );
? std::wstring s2(L"中\u534e人民共和國,龢籦");
? std::cout << "sizeof(char)??? : " << sizeof(char) << std::endl ;
? std::cout << "text??????????? : " << text << std::endl ;
? std::cout << "sizeof(text)??? : " << sizeof(text) << std::endl ; // 算的是字節的數量
? std::cout << "strlen(text)??? : " << strlen(text) << std::endl ;
? std::cout << "text(binary)??? :" ;
? for(size_t i = 0, iMax = strlen(text); i < iMax; ++i)
? {
??? std::cout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned char>(text[i])) ;
? }
? std::cout << std::endl << std::endl ;
? std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl ;
? std::cout << "wtext?????????? : " << wtext << std::endl ;
? std::cout << "wtext?????????? : UNABLE TO CONVERT NATIVELY." << std::endl ;
? std::cout << "sizeof(wtext)?? : " << sizeof(wtext) << std::endl ;
? std::cout << "wcslen(wtext)?? : " << wcslen(wtext) << std::endl ;??????????????????? // 這個函數可以正確的返回字符的個數
? std::cout << "wtext(binary)?? :" ;
? for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
? {
??? std::cout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned short>(wtext[i])) ;
? }
? std::cout << std::endl << std::endl ;
? std::cout << "sizeof(s1) : " << s1.length() << std::endl ;
? std::cout << "s1?????????? : " << s1 << std::endl ;
? std::cout << "s1(binary)?? :" ;
? const char *temp = s1.c_str();
? for(size_t i = 0 ; i < s1.length(); ++i)
? {
??? std::cout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned short>(temp[i])) ;// 二進制的數據與char的類似,只是每個的前面都加上了ff
? }
std::cout << std::endl << std::endl ;
std::locale loc( "chs" );
std::wcout.imbue( loc ); // 設定本地的編碼
std::wcout << L"中國" << std::endl;
? std::wcout << "sizeof(s2) : " << s2.length() << std::endl ;
? std::wcout << "s2?????????? : " << s2 << std::endl ;
? std::wcout << "s2(binary)?? :" ;
? const wchar_t *temp1 = s2.c_str();
? for(size_t i = 0 ; i < s2.length(); ++i)
? {
??? std::wcout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned short>(temp1[i])) ;// 這個和上面的unicode的數據是一致的
? }
? return 0;
}
輸出:
sizeof(char)??? : 1
text??????????? : 中華人民共和國,龢籦
sizeof(text)??? : 21
strlen(text)??? : 20
text(binary)??? : d6 d0 bb aa c8 cb c3 f1 b9 b2 ba cd b9 fa a3 ac fd 98 bb 62
sizeof(wchar_t) : 2
wtext?????????? : 0013FF1C
wtext?????????? : UNABLE TO CONVERT NATIVELY.
sizeof(wtext)?? : 16
wcslen(wtext)?? : a
wtext(binary)?? : 4e2d 534e 4eba 6c11 5171 548c 56fd ff0c 9fa2 7c66
sizeof(s1) : 14
s1?????????? : 中華人民共和國,龢籦
s1(binary)?? : ffd6 ffd0 ffbb ffaa ffc8 ffcb ffc3 fff1 ffb9 ffb2 ffba ffcd ffb9
fffa ffa3 ffac fffd ff98 ffbb 62
中國
sizeof(s2) : 10
s2?????????? : 中華人民共和國,龢籦
s2(binary)?? : 4,e2d 5,34e 4,eba 6,c11 5,171 5,48c 5,6fd f,f0c 9,fa2 7,c66
五 其他
Unicode編碼表到GB2312編碼表映射表
? 1、計算機中所有的數據都用01串來表示,至于一串01到底代表什么是由軟件來設定的。
??? 比如:01111101111101010111110111110101??? 可以理解為一條指令,也可以理解為4個字節的char字符,具體是什么要看這個數據是在代碼段還是數據段。
? 2、字符是人看到的顯示效果(實際上人看到的是字符對應glyph渲染到屏幕上的效果)
? 3、字符有內部的存儲格式(如'中' 在內存中存為 d6d0(gb2312編碼)),這種編碼叫內碼,本質上是將人理解的字符,映射為二進制01串
? 4、字符需要在系統間交換,這時同樣是'中'在簡體中文版OS和繁體中文版OS中內部表示的格式不同,為了進行數據交換,需要能夠標記一個字符,這種編碼叫交換碼,典型的如 unicode、CNS 11643、CCCII
? 5、windows NT一個字符顯示的過程:讀入內碼---轉為unicode(wide char)---找到字體中對應的字模(glyph)---將此glyph(位圖)寫到顯存---調用顯卡刷到顯示器上
二、基本概念
? 1、計算機一開始是在英語國家中產生的,所以計算機的系統一開始都會做一件事:對拉丁字母進行編碼,加上一些控制符號、數學符號等,這便形成了ASCII編碼。
? 2、像英語這樣的拼音文字很容易編碼,因為所有的詞是由26個字母組合而成的,只要編碼26個字母,就可以輸入所有的單詞。但是像中文這樣的象形文字,則只能針對每個字分別進行編碼(因為每個字的字形都不一樣),這樣舊有的編碼是沒法滿足中國人的要求的(你總不能要求只有懂英語的人才能用電腦吧!), 所以老一代的中國程序員就要為中文進行編碼,其中典型的代表是gb2312(簡體)、big5(繁體),所謂的編碼就是確定中文的每個字在內存中對應的01串是什么,比如'國'在內存中用 b9fa(gb2312編碼)表示。
? 3、因為每個國家的文字是不同的,編碼的方式也是不同的,比如b9fa在大陸代表 '國', 在日本就代表特定的日語字符了,那么怎么樣進行信息交換呢?比如我在中國寫了一份源代碼,現在要拿到日本編譯,那么不好意思,編譯不了,因為這里的語義已經改變了。為了能夠進行信息的交換,最簡單的辦法就是為全世界所有的語言的所有的字符都指定一個唯一的編碼,這個就是unicode編碼
? 4、unicode是統一標記,但是unicode有很多種內部存儲的格式,比如unicode為4e2d的字符在內存中可以用3、4或5個字節來表示,這種內部存儲的表示形式叫內碼,典型的實現有utf-8(unix標準)、utf-16(windows標準)、utf-32等
? 5、在簡體中文windows下使用文本編輯器創建的文本文件,使用的編碼方式是gb2312,即編碼方式是根據locale確定的默認的編碼方式。如果需要和類unix系統下的人進行協作開發時就要注意將編碼方式改為utf-8
三、編碼轉換
? 2種內碼進行轉換,需要有個媒介------unicode,一個轉換編碼的例子:(windows平臺) uft8(multibyte)------unicode(wideChar)-----gb2312(multibyte)
int UTF8ToGB(const char* str,char *out)
{
? WCHAR *strSrc;
? TCHAR *szRes;
? int len;
? //獲得臨時變量的大小
? // 后4個參數是輸入的指針,長度,輸出的指針,長度,這里第4個參數是-1,返回unicode字符數
? int i = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
? strSrc = new WCHAR[i+1];// unicode 字符數組
? MultiByteToWideChar(CP_UTF8, 0, str, -1, strSrc, i);
? //獲得臨時變量的大小
? i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
? szRes = new TCHAR[i+1];// 內碼字符的長度
? WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);
? len = (i+1)*sizeof(CHAR);
? memcpy(out,szRes,len);
? out[len+1] ='\0';
? delete []strSrc;
? delete []szRes;
? return len;
}
四、編程語言的支持
1、java? java內置對unicode的支持,即 new String(...) 時,使用的是unicode編碼格式,所有字符串的操作也是針對unicode,要返回指定編碼的字節數組使用getBytes
例子:
2、c、c++
char VS wchar? string VS wstring
例子: vc2005測試
// testString.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <cstring>
#include <iostream>
#include <string>
#include <locale>
int main(int argc, char* argv[])
{
? const char text[] = "中\u534e人民共和國,龢籦" ;??????????????????? // 這個里面存的是字符串的gb2312內碼,但是可以用\u(unicode)來指定字符
? const wchar_t wtext[] = L"中\u534e人民共和國,龢籦" ;?????????????? // 這個里面存的是unicode
? std::string s1("中\u534e人民共和國,龢籦" );
? std::wstring s2(L"中\u534e人民共和國,龢籦");
? std::cout << "sizeof(char)??? : " << sizeof(char) << std::endl ;
? std::cout << "text??????????? : " << text << std::endl ;
? std::cout << "sizeof(text)??? : " << sizeof(text) << std::endl ; // 算的是字節的數量
? std::cout << "strlen(text)??? : " << strlen(text) << std::endl ;
? std::cout << "text(binary)??? :" ;
? for(size_t i = 0, iMax = strlen(text); i < iMax; ++i)
? {
??? std::cout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned char>(text[i])) ;
? }
? std::cout << std::endl << std::endl ;
? std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl ;
? std::cout << "wtext?????????? : " << wtext << std::endl ;
? std::cout << "wtext?????????? : UNABLE TO CONVERT NATIVELY." << std::endl ;
? std::cout << "sizeof(wtext)?? : " << sizeof(wtext) << std::endl ;
? std::cout << "wcslen(wtext)?? : " << wcslen(wtext) << std::endl ;??????????????????? // 這個函數可以正確的返回字符的個數
? std::cout << "wtext(binary)?? :" ;
? for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
? {
??? std::cout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned short>(wtext[i])) ;
? }
? std::cout << std::endl << std::endl ;
? std::cout << "sizeof(s1) : " << s1.length() << std::endl ;
? std::cout << "s1?????????? : " << s1 << std::endl ;
? std::cout << "s1(binary)?? :" ;
? const char *temp = s1.c_str();
? for(size_t i = 0 ; i < s1.length(); ++i)
? {
??? std::cout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned short>(temp[i])) ;// 二進制的數據與char的類似,只是每個的前面都加上了ff
? }
std::cout << std::endl << std::endl ;
std::locale loc( "chs" );
std::wcout.imbue( loc ); // 設定本地的編碼
std::wcout << L"中國" << std::endl;
? std::wcout << "sizeof(s2) : " << s2.length() << std::endl ;
? std::wcout << "s2?????????? : " << s2 << std::endl ;
? std::wcout << "s2(binary)?? :" ;
? const wchar_t *temp1 = s2.c_str();
? for(size_t i = 0 ; i < s2.length(); ++i)
? {
??? std::wcout << " " <<std::hex<< static_cast<unsigned int>(static_cast<unsigned short>(temp1[i])) ;// 這個和上面的unicode的數據是一致的
? }
? return 0;
}
輸出:
sizeof(char)??? : 1
text??????????? : 中華人民共和國,龢籦
sizeof(text)??? : 21
strlen(text)??? : 20
text(binary)??? : d6 d0 bb aa c8 cb c3 f1 b9 b2 ba cd b9 fa a3 ac fd 98 bb 62
sizeof(wchar_t) : 2
wtext?????????? : 0013FF1C
wtext?????????? : UNABLE TO CONVERT NATIVELY.
sizeof(wtext)?? : 16
wcslen(wtext)?? : a
wtext(binary)?? : 4e2d 534e 4eba 6c11 5171 548c 56fd ff0c 9fa2 7c66
sizeof(s1) : 14
s1?????????? : 中華人民共和國,龢籦
s1(binary)?? : ffd6 ffd0 ffbb ffaa ffc8 ffcb ffc3 fff1 ffb9 ffb2 ffba ffcd ffb9
fffa ffa3 ffac fffd ff98 ffbb 62
中國
sizeof(s2) : 10
s2?????????? : 中華人民共和國,龢籦
s2(binary)?? : 4,e2d 5,34e 4,eba 6,c11 5,171 5,48c 5,6fd f,f0c 9,fa2 7,c66
五 其他
Unicode編碼表到GB2312編碼表映射表