kowala's home

kowala's home
這裡是我的學習筆記,陸續增加中。
http://kowala21.blogspot.com

2011-12-26

Dev C++ 中文轉碼測試(UTF-8 to big5) Convert Code in Dev C++ Using iconv.

在目前網際網路普遍的情況下,為了避免亂碼產生,通常都會使用 UTF-8 來編碼,然而,在 Windows 環境下作業,作業系統預設的是區域編碼(big5),這也是常常發生亂碼的原因。本文主要是針對 Dev C++ 開發環境下,使用 iconv 元件來轉碼做說明,對象是 UTF-8 轉 big5 碼,當然,簡體的部分只要改成 gb2312 就行了。

若是使用 Visual C++ 的開發者,可以使用內建的的工具來轉碼,但這不是本文探討對象,請參考這篇。
http://blog.csdn.net/password318/article/details/6958853
主要使用的函式為
MultiByteToWideChar( CP_ACP, 0, chr, strlen(chr)+1, wchar, size/sizeof(wchar[0]) );

WideCharToMultiByte( CP_ACP, 0, wchar, -1, chr, length, NULL, NULL );

在進入主題以前,先簡單的說明 UTF-8 碼與 big5 碼的差別,我們先用筆記本存一段文字,
"中文轉碼測試"
分別存成 ansi 及 UTF-8 ,然後使用 HEX 編輯器開啟它,我們可以看到,ansi 下的中文,一個字佔了 2 bytes,而 UTF-8 下的中文,一個字佔了 3 bytes,並且有前導識別碼 EF BB BF,如下圖所示。



在下面程式碼中,我們必須手動輸入 UTF-8 碼來測試用,如下

    //"中文轉碼測試";
    char utf8buf[] = {
        0xE4,0xB8,0xAD, 0xE6,0x96,0x87, 0xE8,0xBD,0x89,    0xE7,0xA2,0xBC,
        0xE6,0xB8,0xAC, 0xE8,0xA9,0xA6, 0};

因為使用的是字元陣列,所以必須在後面補個 0,作為字串結束。
先來看看執行畫面,轉碼前先顯示來源及目的字串,以供轉碼後對照之用。首先是從 UTF-8 轉到 big5,接著是把 UTF-8 清空,再從 big5 轉回去 UTF-8。



要使用 iconv 之前,我們需先對 Dev C++ 做一些前置工作,包括下載 iconv 元件,lib 載入,及一些 source code 修正等等。

首先是下載 iconv 元件,這裡的範例是使用這個,為了保證能正確運行,請下載一樣的版本。
http://www.d2school.com/cpp_lib_ex/iconv.rar

然後開啟 iconv.h ,找到第 88 行,把 const 前置詞去掉,這是因為不同的作業環境下而做的修正[1]。

extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);

把 const 前置詞去掉,像這樣。

 extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);

接著把一些相關的檔案複製到 Dev C++ 下的資料夾之中

copy iconv.dll C:\Dev-Cpp\bin
copy iconv.h C:\Dev-Cpp\include
copy libiconv.a C:\Dev-Cpp\lib

再來是設定載入 iconv,開啟  專案\專案選項\參數,並加上 -liconv ,如下圖


這樣就完成前置工作了,接著開個專案,把下面的代碼貼上,執行。

/*****************************************************
  Dev C++ 中文轉碼測試 UTF-8 <-> big5
  Convert Code in Dev C++ Using iconv.
  http://kowala21.blogspot.com
  write by kowala.
  Date: 2011-12-26
 
  reference:
  [1]http://wang.yuxuan.org/blog/?itemid=64
  [2]http://www.haogongju.net/art/1081728
  [3]http://worldant.blog.sohu.com/96069463.html
  [4]http://www.gnu.org/software/libiconv
 
  dll download:
  http://www.dlldump.com/
 
  iconv package download:
  http://www.d2school.com/cpp_lib_ex/iconv.rar
******************************************************/
#include <cstdlib>
#include <iostream>
#include <iconv.h>
using namespace std;

void u2b(char src[],char tar[]);
void b2u(char src[],char tar[]);
//-----------------------------------------
int main(int argc, char *argv[]){
    cout << "中文轉碼測試 iconv ..." << endl;

    char utf8buf[] = {
        0xE4,0xB8,0xAD, 0xE6,0x96,0x87, 0xE8,0xBD,0x89,   
        0xE7,0xA2,0xBC, 0xE6,0xB8,0xAC, 0xE8,0xA9,0xA6, 0};
    char big5buf[strlen(utf8buf)/3*2+1];   

    memset(big5buf,0,strlen(big5buf));
    printf("\nUTF-8>\t%s\nbig5 >\t%s",utf8buf,big5buf);
    printf("\nUTF-8\tlen=%d\nbig5\tlen=%d\n",strlen(utf8buf),strlen(big5buf));
       
    u2b(utf8buf,big5buf);   
    printf("\nUTF-8>\t%s\nbig5 >\t%s",utf8buf,big5buf);
    printf("\nbig5\tlen=%d\n",strlen(big5buf));   
   
    memset(utf8buf,0,strlen(utf8buf));
    printf("\nbig5 >\t%s\nUTF-8>\t%s",big5buf,utf8buf);   
    printf("\nbig5\tlen=%d\nUTF-8\tlen=%d\n",strlen(big5buf),strlen(utf8buf));
   
    b2u(big5buf,utf8buf);
    printf("\nbig5 >\t%s\nUTF-8>\t%s",big5buf,utf8buf);   
    printf("\nUTF-8\tlen=%d\n",strlen(utf8buf));   
   
    system("PAUSE");
    return EXIT_SUCCESS;
}
/*----------------
  big5 轉 UTF-8
------------------*/
void b2u(char src[],char tar[]){
    cout << "\nConvert code From big5 to UTF-8...";
    size_t srclen = strlen(src);
    size_t tarlen = srclen/2*3+1;
    memset(tar,0,tarlen);
    iconv_t cd = iconv_open("UTF-8","big5");
    size_t error = iconv(cd,&src,&srclen,&tar,&tarlen);
    iconv_close(cd);
}
/*----------------
  UTF-8 轉 big5
------------------*/
void u2b(char src[],char tar[]){
    cout << "\nConvert code From UTF-8 to big5...";
    size_t srclen = strlen(src);
    size_t tarlen = srclen/3*2+1;   
    memset(tar,0,tarlen);
    iconv_t cd = iconv_open("big5","UTF-8");
    size_t error = iconv(cd,&src,&srclen,&tar,&tarlen);
    iconv_close(cd);
}

最後,轉貼請註明出處,謝謝。

kowala's home
http://kowala21.blogspot.com

參考:

  [1] http://wang.yuxuan.org/blog/?itemid=64
  [2] http://www.haogongju.net/art/1081728
  [3] http://worldant.blog.sohu.com/96069463.html
  [4] http://www.gnu.org/software/libiconv
  [5] http://blog.163.com/fqq_41/blog/static/9602733720081110104834115/