Ansi,UTF8,Unicode編碼(續)

來源:互聯網
上載者:User

1.三種編碼的回顧

Ansi字串我們最熟悉,英文佔一個位元組,漢字2個位元組,以一個\0結尾,常用於txt文字檔。
Unicode字串,每個字元(漢字、英文字母)都佔2個位元組;在VC++的世界裡,Microsoft比較鼓勵使用Unicode,如wchar_t。
UTF8是Unicode一種壓縮形式,英文A在unicode中表示為0x0041,英語中這種儲存方式太浪費,因為浪費了50%的空間,於是就把英文壓縮成1個位元組,成了utf8編碼;但是漢字在utf8中佔3個位元組,顯然用做中文不如ansi合算,這就是中國的網頁用作ansi編碼而國外的網頁常用utf8的原因。程式中把15.7M大小UTF8格式的txt檔案轉化為ANSI後,大小僅為10.8M。

2.轉換函式

一般情況下,可以通過Windows標頭檔下的兩個函數實現各個類型之間的轉換。標頭檔添加:

#include <Windows.h>

多位元組字元集 -> Unicode字元集

int MultiByteToWideChar(  __in   UINT CodePage, // 標識了與多位元組關聯的一個字碼頁值  __in   DWORD dwFlags, // 允許我們進行額外的控制,它會影響帶變音符號(比如重音)的字元。但是一般情況下不適用,賦為 0 即可。  __in   LPCSTR lpMultiByteStr, // 參數指定要轉換的字串  __in   int cbMultiByte, // 指定要轉換串長度的長度(位元組數),如果參數值是-1,函數便可自動判斷源字串的長度  __out  LPWSTR lpWideCharStr, // 指定轉換後Unicode版本的字串記憶體位址  __in   int cchWideChar        // 指定 lpWideCharStr 緩衝區的最大長度。                                // 如果傳入0,函數不會進行轉換,而是返回一個寬字元數(包括終止字元'\0'),                // 只有當緩衝區能夠容納該數量的寬字元時,轉換才會成功。);

Unicode字元集 –> 多位元組字元集

int WideCharToMultiByte(  __in   UINT CodePage,   // 標誌了要與新轉換的字串關聯的字碼頁  __in   DWORD dwFlags,   // 制定額外的轉換控制,一般不需要進行這種程度的控制,而為 dwFlag 傳入 0  __in   LPCWSTR lpWideCharStr, // 指定要轉換的字串的記憶體位址  __in   int cchWideChar,       // 指出該字串的長度,如果傳入 -1 ,則由函數來判斷字串的長度  __out  LPSTR lpMultiByteStr,  // 轉換後的緩衝區  __in   int cbMultiByte,       // 指定 lpMultiByteStr 緩衝區的最大大小(位元組數),如果傳入 0 ,函數返回該目標緩衝區需要的大小  __in   LPCSTR lpDefaultChar,    __out  LPBOOL lpUsedDefaultChar // 寬字元字串中,如果至少有一個字元不能轉換為對應的多位元組形式,函數就會把這個變數設為 TRUE 。如果所有字元都能成功轉換,就會把這個變數設為 FALSE。 通常將此函數傳入 NULL 值。);

只有一個字元在 CodePage 制定的字碼頁中沒有對應的表示時,WideCharToMultiByte 才會使用後兩個參數。在遇到一個不能轉換的字元時,函數便使用 lpDefaultChar 參數指向的字元。如果這個參數指向為 NULL ,函數就會使用一個預設的字元。這個預設的值通常是一個問號。這對檔案操作是非常危險的,因為問號是一個萬用字元。

3.程式實現

程式的標頭檔:

/* *作者:侯凱 *說明:utf8、unicode、utf8相互轉化 *日期:2013-6-4*/#include <iostream>#include <string>#include <fstream>#include <Windows.h> //Windows標頭檔using std::string;using namespace std;

ANSI轉Unicode

void AnsiToUnicode() {    char* sAnsi = "ANSI to Unicode, ANSI 轉換到 Unicode";    //ansi to unicode    int sLen = MultiByteToWideChar(CP_ACP, NULL, sAnsi, -1, NULL, 0);     wchar_t* sUnicode = new wchar_t[sLen];    //wchar_t* sUnicode = (wchar_t*)malloc(sLen*sizeof(wchar_t));    MultiByteToWideChar(CP_ACP, NULL, sAnsi, -1, sUnicode, sLen);     ofstream rtxt("ansitouni.txt");    rtxt.write("\xff\xfe",2);//原因參見上一篇——"小尾"位元組序方式儲存    rtxt.write((char*)sUnicode, sLen*sizeof(wchar_t));    rtxt.close();    delete[] sUnicode;     sUnicode =NULL;     //free(sUnicode);}

Unicode轉ANSI

void UnicodeToAnsi() {    wchar_t *sUnicode = L"Convert Unicode to ANSI, Unicode 轉換為 ANSI";    //unicode to ansi    int sLen = WideCharToMultiByte(CP_ACP, NULL, sUnicode, -1, NULL, 0, NULL, NULL);     char* sAnsi = new char[sLen];    //char* sAnsi = (char*)malloc(sLen);    WideCharToMultiByte(CP_ACP, NULL, sUnicode, -1, sAnsi, sLen, NULL, NULL);     ofstream rtxt("unitoansi.txt");    rtxt.write(sAnsi, sLen);    rtxt.close();    delete[] sAnsi;     sAnsi =NULL;     //free(sAnsi);}

Unicode轉UTF8

void UnicodeToUtf8(){    wchar_t *sUnicode = L"Convert Unicode to UTF8, Unicode 轉換為 UTF8";     // unicode to UTF8     int sLen = WideCharToMultiByte(CP_UTF8, NULL, sUnicode, -1, NULL, 0, NULL, NULL);     //UTF8雖然是Unicode的壓縮形式,但也是多位元組字串,所以可以以char的形式儲存     char* sUtf8 = new char[sLen];      //unicode版對應的strlen是wcslen     WideCharToMultiByte(CP_UTF8, NULL, sUnicode, -1, sUtf8, sLen, NULL, NULL);     ofstream rtxt("unitoutf8.txt");    rtxt.write("\xef\xbb\xbf", 3);//原因參見上一篇    rtxt.write(sUtf8, sLen);    rtxt.close();    delete[] sUtf8;     sUtf8 =NULL; }

UTF8轉Unicode

void Utf8ToUnicode(){        //UTF8 Convert to Unicode, UTF8 轉換為 Unicode,用UE十六進位開啟“轉化為”直接複製過來亂碼,用16進位表示    char* sUtf8 = "UTF8 Convert to Unicode, UTF8 \xe8\xbd\xac\xe6\x8d\xa2\xe4\xb8\xba Unicode";     //UTF8 to Unicode     int sLen = MultiByteToWideChar(CP_UTF8, NULL, sUtf8, -1, NULL, 0);     wchar_t* sUnicode = new wchar_t[sLen];     MultiByteToWideChar(CP_UTF8, NULL, sUtf8, -1, sUnicode, sLen);    ofstream rtxt("utf8touni.txt");    rtxt.write("\xff\xfe",2);    rtxt.write((char*)sUnicode, sLen*sizeof(wchar_t));    rtxt.close();    delete[] sUnicode;     sUnicode =NULL;  }

Ansi轉換utf8和utf8轉換Ansi就是上面2個的結合,把unicode作為中間量,進行2次轉換即可。

4.UTF8轉ANSI

在網路傳輸中,我們常常使用UTF8編碼,但在程式處理時,我們習慣於ANSI編碼,至少目前的VS2010對UTF8碼的顯示是亂碼的。以下函數綜合上述程式,實現了txt檔案UTF8編碼向ANSI編碼的轉化。

//changeTxtEncoding修改字串的編碼  char* changeTxtEncoding(char* szU8){      int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, -1, NULL, 0);      wchar_t* wszString = new wchar_t[wcsLen];    ::MultiByteToWideChar(CP_UTF8, NULL, szU8, -1, wszString, wcsLen);    cout<<wszString<<endl;    int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, -1, NULL, 0, NULL, NULL);  //wcslen(wszString)    char* szAnsi = new char[ansiLen];      ::WideCharToMultiByte(CP_ACP, NULL, wszString, -1, szAnsi, ansiLen, NULL, NULL);     delete[] wszString;    return szAnsi;  }void changeTextFromUtf8ToAnsi(const char* filename)  {      ifstream infile;    string strLine="";    string strResult="";      infile.open(filename);    infile.seekg(3, ios::beg);    if (infile)      {          while(!infile.eof())        {              getline(infile,strLine);              strResult+=strLine+"\n";        }      }    infile.close();    char* changeTemp=new char[strResult.length()+1];    changeTemp[strResult.length()]='\0'; //問題記錄    strcpy(changeTemp, strResult.c_str()); //const char*轉化char*的方法    char* changeResult=changeTxtEncoding(changeTemp);     strResult=changeResult;      ofstream outfile;      outfile.open("ANSI.txt");      outfile.write(strResult.c_str(), strResult.length());      outfile.flush();      outfile.close();    delete[] changeResult;    delete[] changeTemp;}

問題記錄:
關於字串的長度a.String類型的length()和size()函數都返回字串的真實大小,不包括'\0‘ ;
b.char*類型的strlen()函數也是返回字串的真實大小,不包括'\0‘ ;
c.注意,sizeof()函數包含'\0‘ ,如char str[] = “Hello” ;則sizeof (str ) = 6。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.