字符編碼--第3章 字符的存儲--ANSI編碼

第11節 ANSI編碼程序員

爲使計算機支持更多語言,一般使用 0x80~0xFF 範圍的 2 個字節來表示 1 個字符。好比:漢字 '中' 在中文操做系統中,使用 [0xD6,0xD0] 這兩個字節存儲。數組

不一樣的國家和地區制定了不一樣的標準,由此產生了 GB23十二、GBK、GB18030、Big五、Shift_JIS 等各自的編碼標準。這些使用多個字節來表明一個字符的各類漢字延伸編碼方式,稱爲 ANSI 編碼。在簡體中文Windows操做系統中,ANSI 編碼表明 GBK 編碼;在繁體中文Windows操做系統中,ANSI編碼表明Big5;在日文Windows操做系統中,ANSI 編碼表明 Shift_JIS 編碼。編輯器

不一樣 ANSI 編碼之間互不兼容,當信息在國際間交流時,沒法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。ide

ANSI編碼表示英文字符時用一個字節,表示中文用兩個或四個字節。函數

 

第12節 全角和半角測試

全角(大陸、日本、韓國稱全角;臺灣、香港稱全形;也稱全寬或全碼)和半角(大陸、日本、韓國稱半角;臺灣、香港稱半形;也稱半寬或半碼),是計算機中,中、日、韓文的CJKV字符的顯示格式。字體

傳統上,英語或拉丁字母語言使用的電腦系統,每個字母或符號,都是使用一字節的空間(一字節由8位元組成,共256個編碼空間)來儲存;而漢語、日語及韓語文字,因爲數量大大超過256個,故慣常使用兩字節來儲存一個字符,在使用固定寬度文字的地方(如DOS、部分文字編輯器等),爲了使字體看起來齊整,英文字母、數字及其餘符號,也由原來只佔一個字空間,改成一律佔用兩個字的空間來顯示,而且使用兩個字節來儲存。因此,中、日、韓等文字稱爲全形字符,相比起來,拉丁字母或數字就稱爲半形字符。ui

JIS X 0201編碼表把日語的片假名放進一字節的空間,故又稱爲「半角片假名」。編碼

 

半形假名spa

半形假名(日文:半角カナ)是對 JIS X 0201 標準收納的片假名、幾個基本日文標點符號(日文:句読點 或 約物)、濁點和半濁點的統稱。其包含日文的最基礎符號,能以最簡約的方式表達日語。每一個「半形假名」只須要八位元,能夠當作是對 ISO 646 / ASCII 的擴充;佔用的文字寬度亦同樣,一般只有普通漢字的一半,故稱爲「半形假名」。

例如普通(全形)的片假名「カ」,半形的是「カ」。平假名和漢字並沒有半形版本。

 

區位碼

區位碼是指每一個漢字的GB2312編碼的對應表示,以4位十進制數字表示。例如「啊」字的區位碼是1601。

國標碼的內碼是指每一個漢字未經處理的GB2312編碼,以4位十六進制數字表示。例如「啊」字的國標碼是B0A1(與國標碼對比:0xB0=0xA0+16,0xA1=0xA0+1)。

國標碼、區位碼都屬於「無理碼」(即沒有什麼道理可講,就得背),直接向計算機輸入區位碼而獲得漢字的方法叫作區位輸入法(相應地,輸入國標碼而獲得漢字的方法叫作GB內碼輸入法)。在DOS時代,許多中文系統都實現了國標碼及區位碼輸入法,以便程序員進行輸入測試。普通用戶通常不使用這些輸入法,在DOS被Windows系統取代後,國標碼和區位碼輸入法已經趨於消亡。

Windows 95至2000、Me中,有「區位輸入法」和「內碼輸入法」;Windows XP中,有「中文(簡體) - 內碼」;Windows Vista起,該輸入法被移除,須從XP系統中移植WinGB.IME方可以使用。

 

 

 

MBCS(Multi-Byte Chactacter System,即多字節字符系統)

它是編碼的一種類型,而不是某個特定編碼的名稱。

    字符基礎:ASCII,DBCS,Unicode

 全部的string類都是以C-style字符串爲基礎的。C-style字符串是字符數組。字符類型有三種編碼格式:

  第一種是單字節字符集(single byte character set or SBCS)。在這種編碼格式下,全部字符都只用 一個字節表示,ASCII碼就是單字節字符。用"0"來表示一個字節的結束。

  第二種編碼格式是多字節字符集(multi-byte character set or MBCS)。在Windows裏的MBCS包含兩種字符類型:單字節字符(single byte characters)和雙字節字符(double byte characters)。因爲Windows 裏使用的多字節字符絕大部分是兩個字節長,MBCS常被DBCS代替。

   第三種編碼格式是Unicode。Unicode是一種全部的字符都使用兩個字節編碼的編碼模式。Unicode字符有時也被稱做寬字符。

 Unicode與MBCS的區別是:MBCS字符可使用不一樣長度的字節編碼。

 單字節字符包含拉丁文字母表及ASCII碼和DOS操做系統定義的圖形字符。雙字節字符被用來表示東亞及中東的語言。Unicode被用來COM及Windows NT操做系統內部。

 char是單字節字符。雙字節字符也能夠用char類型來進行操做。Unicode字符用wchar_t來表示。Unicode字符和字符串常量用前綴L來表示。例如:

 wchar_t wch = L"1";

 wchar_t* wsz = L"Hello";

 單字節字符串在內存中:每一個字符佔一個字節按順序依次存儲。最後以單字節表示的0結束。例如:"Bob"在內存中的存儲形式:

 |-------------------------------|

 |42    |   6F   |   62   | 00   |

 |-------------------------------|

 |B     |   o    |   b    | BOS  |

 |-------------------------------|

 Unicode的存儲形式:

    --------------------------------------------

 |   42 00 |   6F 00  |   62 00  |   00 00  |

 |------------------------------------------|

 |   B     |    o     |   b      |   BOS    |

 |------------------------------------------|

 Win32 API中的MBCS和Unicode

 儘管你也許歷來沒有注意過,Win32中的每一個與字符串相關的API和message都有兩個版本。一個版本按受MBCS字符串,另外一個接受Unicode字符串。例如:根本沒有SetWindowText()這個API,相反有SetWindowTextA()和SetWindowTextW()。

 後綴A代表這是MBCS函數,後綴W表示這是Unicode版本的函數。

 當你build一個Windows程序,你能夠選擇是用MBCS或者Unicode API,若是你用vc嚮導而且沒有改過預處理的設置。那代表你用的是MBCS版本。

 當使用MBCS API來build程序時,UNICODE沒有被定義,因此預處理器看到:

 #define SetWindowText SetWindowTextA

 這個宏把全部對SetWindowText的調用都轉換成真正的API函數SetWindowTextA.若是你想把默認使用的API函數變成Unicode版的,你能夠在預處理器設置中,把_MBCS從預約義的宏列表中刪除。而後添加UNICODE和_UNICODE(須要兩個都定義,由於不一樣的頭文件可能使用不一樣的宏。)

 使用TCHAR類型

 TCHAR是一種字符串類型,它讓你在以MBCS和UNICODE來build程序時可使用一樣的代碼;不須要使用繁瑣的宏定義來包含你的代碼。TCHAR的定義以下:

 #ifdef UNICODE

 typedef wchar_t TCHAR;

 #else

 typedef char TCHAR;

 #endif

 還有一個宏來處理定義Unicode字符串常量時所需的L前綴。

 #ifdef UNICODE

 #define _T(x) L##X

 #else

 #define _T(x)x

 #endif

 ##是一個預處理操做符,它能夠把兩個參數連在一塊兒。若是你的代碼中須要字符串常量,在它前面加上_T宏,若是你使用Unicode來build,它會在字符串常量前加上L前綴。

 Windows API是用TCHAR來定義的,在編譯時,它能夠根據你是否認義_MBCS或_UNICODE被編譯成MBCS或者Unicode字符。

 類型             含義

 WCHAR            Unicode character(wchar_t)

 TCHAR            MBCS or Unicode character.

 LPSTR            string of char (char*)

 LPCSTR           const string of char(const char*)

 LPWSTR           string of WCHAR(WCHAR*)

 LPCWSTR          constant string of WCHAR(const WCHAR*)

 LPTSTR           string of TCHAR(TCHAR*)

 LPCTSTR          constant string of TCHAR(const TCHAR*)

 

 雜談:

 計算機發明後,爲了在計算機中表示字符,人們制定了一種編碼,叫作ASCII碼,ASCII碼由一個字節中的7位(bit)表示,範圍是0x00-0x7F共128個字符。用這128個數字表示abcd...ABCD...1234....這些字符。後來又擴展了ASCII碼的定義,使用一個字節的所有8位(bit)來表示字符了。這就叫擴展 ASCII碼。範圍是0x00-0xFF共256個字符。

 後來,中國人利用連續2個擴展ASCII碼的擴展區域(0xA0之後)來表示一個漢字,該方法的標準叫GB-2312。後來,日文、韓文、阿拉伯文、臺灣繁體都使用相似的方法擴展了本地字符集的定義,如今統一稱爲MBCS字符集(多字節字符集)。這種方法是有缺陷的,由於各個國家的定義的字符集有交集,所以使用GB2312的軟件,就不能在BIG-5的環境下運行(顯示亂碼)。

 爲了把全世界的全部的文字符號都統一進行編碼,因而制定了UNICODE標準字符集。UNICODE使用2個字節表示一個字符。這下終於好啦,全世界任何一個地區的軟件,能夠 不用修改就能在另外一個地區運行了。UNICODE的範圍是0x0000-0xFFFF共6萬多個字符。

 在程序中使用各類字符集的方法:

 const char* p = "Hello"; //使用ASCII碼

 const char* p = "你好"; //使用MBCS字符集,因爲MBCS徹底兼容ASCII碼,多數狀況,咱們並不嚴格區分他們。

    LPCSTR p = "Hello,你好"; //意義同上。

 const WCHAR *p = L"Hello,你好";使用UNICODE字符集。

 //若是預約義了_UNICODE,則表示使用UNICODE字符集,若是定義了_MBCS,則表示使用MBCS

 const TCHAR *p = _T("Hello 您好");

 LPCTSTR p = _T("Hello,你好");//意義同上。

 

 

多字節與UTF-八、Unicode之間的轉換

// 多字節編碼轉爲UTF8編碼 
bool MBToUTF8(vector<char>& pu8, const char* pmb, int32 mLen) 
{ 
 // convert an MBCS string to widechar  
 int32 nLen = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, NULL, 0); 
  
 WCHAR* lpszW = NULL; 
 try 
 { 
    lpszW = new WCHAR[nLen]; 
 } 
 catch(bad_alloc &memExp) 
 { 
    return false; 
 } 
 
 int32 nRtn = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, lpszW, nLen); 
  
 if(nRtn != nLen) 
 { 
    delete[] lpszW; 
    return false; 
 } 
 // convert an widechar string to utf8 
 int32 utf8Len = WideCharToMultiByte(CP_UTF8, 0, lpszW, nLen, NULL, 0, NULL, NULL); 
 if (utf8Len <= 0) 
 { 
     return false; 
 } 
 pu8.resize(utf8Len); 
 nRtn = WideCharToMultiByte(CP_UTF8, 0, lpszW, nLen, &*pu8.begin(), utf8Len, NULL, NULL); 
 delete[] lpszW; 
 
 if (nRtn != utf8Len) 
 { 
     pu8.clear(); 
     return false; 
 } 
 return true; 
} 
 
// UTF8編碼轉爲多字節編碼 
bool UTF8ToMB(vector<char>& pmb, const char* pu8, int32 utf8Len) 
{ 
    // convert an UTF8 string to widechar  
    int32 nLen = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, NULL, 0); 
 
    WCHAR* lpszW = NULL; 
    try 
    { 
        lpszW = new WCHAR[nLen]; 
    } 
    catch(bad_alloc &memExp) 
    { 
        return false; 
    } 
 
    int32 nRtn = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, lpszW, nLen); 
 
    if(nRtn != nLen) 
    { 
        delete[] lpszW; 
        return false; 
    } 
 
    // convert an widechar string to Multibyte  
    int32 MBLen = WideCharToMultiByte(CP_ACP, 0, lpszW, nLen, NULL, 0, NULL, NULL); 
    if (MBLen <=0) 
    { 
        return false; 
    } 
    pmb.resize(MBLen); 
    nRtn = WideCharToMultiByte(CP_ACP, 0, lpszW, nLen, &*pmb.begin(), MBLen, NULL, NULL); 
    delete[] lpszW; 
 
    if(nRtn != MBLen) 
    { 
        pmb.clear(); 
        return false; 
    } 
    return true; 
} 
 
// 多字節編碼轉爲Unicode編碼 
bool MBToUnicode(vector<wchar_t>& pun, const char* pmb, int32 mLen) 
{ 
    // convert an MBCS string to widechar  
    int32 uLen = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, NULL, 0); 
 
    if (uLen<=0) 
    { 
        return false; 
    } 
    pun.resize(uLen); 
 
    int32 nRtn = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, &*pun.begin(), uLen); 
 
    if (nRtn != uLen) 
    { 
        pun.clear(); 
        return false; 
    } 
    return true; 
} 
 
//Unicode編碼轉爲多字節編碼 
bool UnicodeToMB(vector<char>& pmb, const wchar_t* pun, int32 uLen) 
{ 
    // convert an widechar string to Multibyte  
    int32 MBLen = WideCharToMultiByte(CP_ACP, 0, pun, uLen, NULL, 0, NULL, NULL); 
    if (MBLen <=0) 
    { 
        return false; 
    } 
    pmb.resize(MBLen); 
    int nRtn = WideCharToMultiByte(CP_ACP, 0, pun, uLen, &*pmb.begin(), MBLen, NULL, NULL); 
 
    if(nRtn != MBLen) 
    { 
        pmb.clear(); 
        return false; 
    } 
    return true; 
} 
 
// UTF8編碼轉爲Unicode 
bool UTF8ToUnicode(vector<wchar_t>& pun, const char* pu8, int32 utf8Len) 
{ 
    // convert an UTF8 string to widechar  
    int32 nLen = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, NULL, 0); 
    if (nLen <=0) 
    { 
        return false; 
    } 
    pun.resize(nLen); 
    int32 nRtn = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, &*pun.begin(), nLen); 
 
    if(nRtn != nLen) 
    { 
        pun.clear(); 
        return false; 
    } 
 
    return true; 
} 
 
// Unicode編碼轉爲UTF8 
bool UnicodeToUTF8(vector<char>& pu8, const wchar_t* pun, int32 uLen) 
{ 
    // convert an widechar string to utf8 
    int32 utf8Len = WideCharToMultiByte(CP_UTF8, 0, pun, uLen, NULL, 0, NULL, NULL); 
    if (utf8Len<=0) 
    { 
        return false; 
    } 
    pu8.resize(utf8Len); 
    int32 nRtn = WideCharToMultiByte(CP_UTF8, 0, pun, uLen, &*pu8.begin(), utf8Len, NULL, NULL); 
 
    if (nRtn != utf8Len) 
    { 
        pu8.clear(); 
        return false; 
    } 
    return true; 
}

 

字符編碼-- Unicode

相關文章
相關標籤/搜索