多字節字符集與Unicode字符集


  在計算機中字符通常並不是保存為圖像,每個字符都是使用一個編碼來表示的,而每個字符究竟使用哪個編碼代表,要取決於使用哪個字符集(charset)。 

多字節字符集:

  在最初的時候,Internet上只有一種字符集——ANSI的ASCII字符集,它使用7 bits來表示一個 字符,總共表示128個字符,其中包括了 英文字母、數字、標點符號等常用字符。之后,又進行擴展,使用8 bits表示一個字符,可以表示256個字符,主要在原來的7 bits字符集的基礎上加入了一些特殊符號。后來,由於各國語言的加入,ASCII已經不能滿足信息交流的需要,為了能夠表示其它國家的文字,各國在 ASCII的基礎上制定了自己的字符集,這些從ANSI標准派生的字符集被習慣的統稱為ANSI字符集,它們正式的名稱應該是MBCS(Multi-Byte Chactacter System,即多字節字符系統)。這些派生字符集的特點是以ASCII 127 bits為基礎,兼容ASCII 127,他們使用大於128的編碼作為一個Leading Byte,緊跟在Leading Byte后的第二(甚至第三)個字符與 Leading Byte一起作為實際的編碼。這樣的字符集有很多,我們常見的GB-2312就是其中之一。

Unicode字符集:

  Unicode的學名 是"Universal Multiple-Octet Coded Character Set",簡稱為UCS。UCS可以看作是"Unicode Character Set"的縮寫。UCS只是規定如何編碼,並沒有規定如何傳輸、保存這個編碼。UTF是“UCS Transformation Format”的縮寫。

  Unicode字符集有多種編碼形式,它固定使用16 bits(兩個字節、一個字)來表示一個字符,共可以表示65536個字符。將世界上幾乎所有語言的常用字符收錄其中,方便了信息交流。標准的Unicode稱為UTF-16。后來為了雙字節的Unicode能夠在現存的處理單字節的系統上正確傳輸,出現了UTF-8(注意UTF-8是編碼,它屬於Unicode字符集),使用類似MBCS的方式對Unicode進行編碼。UTF-8以字節為編碼單元,沒有字節序的問題。UTF-16以兩個字節為編碼單元。

  UTF-16包括三種:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian),UTF-16需要通過在文件開頭以名為BOM(Byte Order Mark)的字符來表明文件是Big Endian還是Little Endian。Unicode規范中推薦的標記字節順序的方法是BOM(Byte Order Mark)。在UCS編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中。UCS規范建議我們在傳輸字節流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。這樣如果接收者收到FEFF,就表明這個字節流是Big-Endian的;如果收到FFFE,就表明這個字節流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。

  UTF-8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗證一下)。所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。

  Windows就是使用BOM來標記文本文件的編碼方式的。

  L是用來標志一個字符(串)為寬字符(串),當你在VS2005以上版本的IDE工作時,可以選擇工作於這兩種不同的編碼方式下,而在Unicode方式下,則要對字符(串)常量前添加L來告訴編譯器它是寬字符。MS為我們定義了好幾個相關的宏:_T(定義於tchar.h)、_TEXT(同樣定義於tchar.h)。

   TEXt():如果定義了Unicode,標識字符為Unicode;否則,為ANSI字符集。在VS2010使用Unicode字符集下:
//    MessageBox("Test");  //錯誤

//    MessageBox(_T("Test"));
//    MessageBox(TEXT("Test"));
      MessageBox(_TEXT("Test"));

  

  對於為什么使用Unicode?(以下引自《windows核心編程》)
  開發應用程序的時候,強烈建議你使用Unicode字符和字符串,理由如下:

  • Unicode使程序的本地化變得更容易;
  • 使用Unicode,只需發布一個二進制(.exe或DLL)文件,即可支持所有語言;
  • Unicode代碼執行速度更快,占用內存更少,提升了應用程序的效率。自從Windows2K開始,Win的系統內核開始完全支持並完全應用Unicode編寫,所有ANSI字符在進入底層前,都會被相應的API轉換成Unicode。所以,如果你一開始就使用Unicode,則可以減少轉換的用時和RAM開銷。
  • 使用Unicode,你的應用程序能輕松調用所有不反對使用(nondeprecated)的Windows函數,因為一些Windows函數提供了只能處理Unicode字符和字符串的版本;
  • 使用Unicode,你的代碼很容易與COM集成(后者要求使用Unicode字符和字符串);
  • 使用Unicode,你的代碼很容易與.NET Framework集成(后者要要求使用Unicode字符和字符串);
  • 使用Unicode,能保證你的代碼能夠輕松操縱你自己的資源(其中的字符串總是Unicode的);
  • 世界上大多數程序用的字符集都是Unicode,因為Unicode有利於程序國際化和標准化;

  

  wchar_t與char類型間的轉換:

#include<iostream>  
#include<Windows.h>
using namespace std;  
class CUser  
{  
public:  
    CUser();  
    virtual ~CUser();  
    char* WcharToChar(wchar_t* wc);//寬字節轉單字節   
    wchar_t* CharToWchar(char* c); //單字節轉寬字節   
    void Release();//釋放資源   
private:  
    char* m_char;  
    wchar_t* m_wchar;  
};  
/////////////////////////////////////////////////////////////////////////////////////   
/*字符類型        wchar_t     char 
/*獲取字符長度    wcslen()    strlen() 
/*連接兩個字符串  wcscat()    strcpy() 
/*復制字符串      wcscpy()    strcpy() 
/*比較兩個字符串  wcscmp()    strcmp() 
/*具體參數詳見www.linuxidc.com*/  
////////////////////////////////////////////////////////////////////////////////////   
CUser::CUser():m_char(NULL),m_wchar(NULL)  
{  
}  
CUser::~CUser()  
{  
    Release();  
}  

//寬字節轉單字節   
char* CUser::WcharToChar(wchar_t* wc)  
{  
    Release();  
    int len= WideCharToMultiByte(CP_ACP,0,wc,wcslen(wc),NULL,0,NULL,NULL);  
    m_char=new char[len+1];  
    WideCharToMultiByte(CP_ACP,0,wc,wcslen(wc),m_char,len,NULL,NULL);  
    m_char[len]='\0';  
    return m_char;  
}  

//單字節轉寬字節   
wchar_t* CUser::CharToWchar(char* c)  
{  
    Release();  
    int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);  
    m_wchar=new wchar_t[len+1];  
    MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);  
    m_wchar[len]='\0';  
    return m_wchar;  
}  

//釋放資源   
void CUser::Release()  
{  
    if(m_char)  
    {  
        delete m_char;  
        m_char=NULL;  
    }  
    if(m_wchar)  
    {  
        delete m_wchar;  
        m_wchar=NULL;  
    }  
} 

使用如下:

WCHAR* wc;  
CUser u;  
char* c=u.WcharToChar(wc);  
cout<<c<<endl; 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM