日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

iconv字符編碼轉(zhuǎn)換全攻略

 quasiceo 2013-02-20

iconv字符編碼轉(zhuǎn)換全攻略

分類: 開源庫(kù)介紹 1169人閱讀 評(píng)論(0) 收藏 舉報(bào)

        iconv(http://www./software/libiconv/)是一個(gè)開源的字符編碼轉(zhuǎn)換庫(kù),可以“方便”的完成幾乎所有的編碼轉(zhuǎn)換工作。說(shuō)簡(jiǎn)單是因?yàn)?,它常用的接口就三個(gè),iconv_open  iconv   iconv_close,但是即便是只有三個(gè)接口,要想使用正確也不容易。這里把一些基本概念和使用細(xì)節(jié)記錄下來(lái),希望能成為一篇最實(shí)用的入門教程。
 
一、字符編碼基本概念
      更詳細(xì)的內(nèi)容可以參考百度百科(http://baike.baidu.com/view/1204863.htm),或是自行g(shù)oogle。這里會(huì)記錄最核心的幾個(gè)概念。
      1、ASCII編碼,就是英文顯示文字所需要的256個(gè)字符(比如,英文字母、數(shù)字、標(biāo)點(diǎn)符號(hào)等等)

      2、ANSI編碼,像中文,肯定不能只用256個(gè)字符就代表所有漢字。因此對(duì)ASCII碼表進(jìn)行了擴(kuò)展,使用兩個(gè)(或多個(gè))字節(jié),代表一個(gè)漢字。類似的,不同的國(guó)家和地區(qū)制定了不同的標(biāo)準(zhǔn),這些使用 2 個(gè)字節(jié)來(lái)代表一個(gè)字符的各種延伸編碼方式,稱為 ANSI 編碼。也就是說(shuō),ANSI是一種對(duì)ASCII碼表進(jìn)行擴(kuò)展的泛稱,不同語(yǔ)言操作系統(tǒng),其代表的編碼方式不一樣。比如中文操作系統(tǒng),ANSI編碼就代指GB2312;日文操作系統(tǒng)ANSI編碼就代指JIS。
      
      3、Unicode編碼,Unicode是一個(gè)超大的集合,也是一個(gè)統(tǒng)一的標(biāo)準(zhǔn),可以容納世界上的所有語(yǔ)言符號(hào)。每個(gè)符號(hào)的編碼都不一樣,比如,U+0639表示阿拉伯字母Ain,U+0041表示英語(yǔ)的大寫字母A,“漢”這個(gè)字的Unicode編碼是U+6C49。

      4、代碼頁(yè)(codepage),Unicode是一個(gè)世界統(tǒng)一的標(biāo)準(zhǔn),也就是說(shuō),如果一個(gè)文本是用Unicode方式編碼的,那么它可以同時(shí)顯示中文、日文、阿拉伯文等等,并且是在任何系統(tǒng)上都可以正常顯示的。但是由于ANSI編碼之間互不兼容,因此就需要有一個(gè)標(biāo)識(shí)來(lái)表明不同的ANSI編碼到Unicode之間的映射關(guān)系(也就是不同編碼之間的映射關(guān)系),這個(gè)就是代碼頁(yè)。比如簡(jiǎn)體中文的代碼頁(yè)是CP_936(中文系統(tǒng)默認(rèn)的代碼頁(yè)),這個(gè)也就是windows API中MultiByteToWideChar第一個(gè)參數(shù)所代表的含義。如果不標(biāo)明代碼頁(yè),系統(tǒng)是不知道如何進(jìn)行編碼轉(zhuǎn)換的。

    5、SBCS(單字節(jié)字符集),MBCS(多字節(jié)字符集),DBCS(寬字節(jié)字符集),分別對(duì)應(yīng)上面提到的ASCII編碼、ANSI編碼、Unicode編碼。

    6、中文常見編碼:GB2312(CP_20936)->GBK(CP_936)->GB18030(CP_54936),三種編碼方式向下兼容,也就是說(shuō)GB18030包含GB2312的所有字符。GB18030在2000年取代GBK成為正式國(guó)家標(biāo)準(zhǔn)。

    7、UCS(Unicode Character Set):UCS-2規(guī)定了2個(gè)字節(jié)代表一個(gè)文字,還有UCS-4規(guī)定了4個(gè)字節(jié)代表一個(gè)文字。我們工作中幾乎總是在和UCS-2打交道。

   8、UTF(UCS Transformation Format):UCS只是規(guī)定的如何編碼,但是沒(méi)有規(guī)定如何傳輸、保存這個(gè)編碼。UTF則規(guī)定了由幾個(gè)字節(jié)保存這個(gè)編碼。UTF-7,UTF-8,UTF-16都是比較常見的編碼方式。UTF-8編碼與Unicode編碼并不相同,但是它們之間可以通過(guò)計(jì)算進(jìn)行轉(zhuǎn)換,而不像ANSI和Unicode之間必須通過(guò)一個(gè)映射表來(lái)人為規(guī)定其對(duì)應(yīng)關(guān)系。UTF-16完全對(duì)應(yīng)于UCS-2,并可通過(guò)計(jì)算代表一部分UCS-4文字。還有UTF-32則是完全對(duì)應(yīng)于UCS-4,不過(guò)很不常見就是了。

   9、UTF-8是與ASCII碼兼容的,英文字母1個(gè)字節(jié),漢字通常是3個(gè)字節(jié);UTF-16的所有字符都是用2個(gè)字節(jié)進(jìn)行保存,其編碼與Unicode是等價(jià)的。UTF-16又分為UTF-16LE(little endian)和UTF-16BE(big endian),比如一個(gè)字母'a',如果按utf-8來(lái)存,就是0x61;如果按utf-16le來(lái)存就是0x61 0x00(低有效位在前);如果按utf-16be來(lái)存就是0x00 0x61(高有效位在前)。這個(gè)也就是我們用記事本另存文件的時(shí)候可以選擇的幾個(gè)編碼方式的含義。

   10、BOM(byte order mark),上面提到的utf-8 utf-16le utf16-be都是unicode編碼,但是系統(tǒng)依然無(wú)法正確解析一個(gè)文本文件,即便已經(jīng)知道它是unicode編碼。所以就有了這樣的規(guī)定:在文本文件的最開頭插入幾個(gè)字節(jié)的標(biāo)識(shí),來(lái)說(shuō)明編碼方式。utf-8的BOM是0xef 0xbb 0xbf,utf-16le的BOM是0xff 0xfe,utf16-be的BOM是0xfe 0xff。事實(shí)上BOM并不是必須的,它僅僅是幫助程序自動(dòng)判斷編碼方式使用的,如果我們手動(dòng)選擇編碼方式(像ANSI一樣),即便沒(méi)有BOM,也是可以正常顯示的。反過(guò)來(lái)說(shuō),程序讀文本文件的時(shí)候要先讀文本開始的三個(gè)字節(jié)判斷下編碼方式。


二、iconv支持的編碼格式:

European languages
ASCII, ISO-8859-{1,2,3,4,5,7,9,10,13,14,15,16}, KOI8-R, KOI8-U, KOI8-RU, CP{1250,1251,1252,1253,1254,1257}, CP{850,866,1131}, Mac{Roman,CentralEurope,Iceland,Croatian,Romania}, Mac{Cyrillic,Ukraine,Greek,Turkish}, Macintosh
Semitic languages
ISO-8859-{6,8}, CP{1255,1256}, CP862, Mac{Hebrew,Arabic}
Japanese
EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP, ISO-2022-JP-2, ISO-2022-JP-1
Chinese
EUC-CN, HZ, GBK, CP936, GB18030, EUC-TW, BIG5, CP950, BIG5-HKSCS, BIG5-HKSCS:2004, BIG5-HKSCS:2001, BIG5-HKSCS:1999, ISO-2022-CN, ISO-2022-CN-EXT
Korean
EUC-KR, CP949, ISO-2022-KR, JOHAB
Armenian
ARMSCII-8
Georgian
Georgian-Academy, Georgian-PS
Tajik
KOI8-T
Kazakh
PT154, RK1048
Thai
ISO-8859-11, TIS-620, CP874, MacThai
Laotian
MuleLao-1, CP1133
Vietnamese
VISCII, TCVN, CP1258
Platform specifics
HP-ROMAN8, NEXTSTEP
Full Unicode
UTF-8 
UCS-2, UCS-2BE, UCS-2LE 
UCS-4, UCS-4BE, UCS-4LE 
UTF-16, UTF-16BE, UTF-16LE 
UTF-32, UTF-32BE, UTF-32LE 
UTF-7 
C99, JAVA
Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment)
UCS-2-INTERNAL, UCS-4-INTERNAL
Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment, and with OS and locale dependent semantics)
char, wchar_t 
The empty encoding name "" is equivalent to "char": it denotes the locale dependent character encoding.
When configured with the option --enable-extra-encodings, it also provides support for a few extra encodings:
European languages
CP{437,737,775,852,853,855,857,858,860,861,863,865,869,1125}
Semitic languages
CP864
Japanese
EUC-JISX0213, Shift_JISX0213, ISO-2022-JP-3
Chinese
BIG5-2003 (experimental)
Turkmen
TDS565
Platform specifics
ATARIST, RISCOS-LATIN1

    通過(guò)第一部分的講解,這些編碼格式應(yīng)該看著比較清晰了。比如gb2312-->unicode的轉(zhuǎn)化就是GBK(或者是gb18030  cp936,我們之前說(shuō)過(guò),大多數(shù)情況這些是等價(jià)的)到ucs-2(或者是utf-16,如果文本信息中沒(méi)有BOM就要特別指定utf-16le或是utf-16be)的轉(zhuǎn)化。這些就是我們將要用到的編碼轉(zhuǎn)換的參數(shù)。

三、iconv函數(shù)詳解
1、iconv_t iconv_open (const char* tocode, const char* fromcode);

如果轉(zhuǎn)換編碼不支持(通常是寫錯(cuò)了),那么就返回-1,否則返回一個(gè)句柄。tocode和fromcode傳的就是上面列表中的參數(shù)。補(bǔ)充,如果在tocode后面追加"//TRANSLIT"(比如"utf-8//TRANSLIT"),那么如果一個(gè)字符無(wú)法被轉(zhuǎn)換,則會(huì)自動(dòng)尋找相似字符進(jìn)行替換。如果追加的是"//IGNORE",則會(huì)忽略無(wú)法轉(zhuǎn)換的字符。

2、size_t iconv (iconv_t cd,
              const char* * inbuf, size_t * inbytesleft,
              char* * outbuf, size_t * outbytesleft);
        真正用于轉(zhuǎn)換的函數(shù),cd就是iconv_open返回的句柄,要注意,iconv會(huì)修改傳入的參數(shù),所以要保存好原始o(jì)utbuf指針。轉(zhuǎn)換完畢后inbuf會(huì)指向無(wú)法成功轉(zhuǎn)換而被截?cái)嗟牡谝粋€(gè)字符,inbutesleft顧名思義就是有多少字符尚未轉(zhuǎn)換,如果全部轉(zhuǎn)換成功當(dāng)然就是0了,outbuf指向輸出緩存的轉(zhuǎn)換后的字符的末尾,outbutesleft表明輸出緩存尚有多少自己剩余。
這個(gè)函數(shù)有很多細(xì)節(jié)需要注意。如果inbuf中遇到非法字節(jié)序列會(huì)截?cái)啵@時(shí)inbuf就指向被截?cái)嗟牡谝粋€(gè)字節(jié)。這種情況一般出現(xiàn)在編碼指定錯(cuò)誤或者是數(shù)據(jù)源被截?cái)嗟臅r(shí)候。比如我們指定gb2312轉(zhuǎn)ut-8,但是數(shù)據(jù)源里出現(xiàn)阿拉伯字符,這個(gè)時(shí)候就會(huì)發(fā)生截?cái)唷?         如果outbuf空間不足,也會(huì)發(fā)生截?cái)?,不過(guò)這種情況相對(duì)少見,因?yàn)槲覀兂绦蛑袝?huì)保證輸出緩存有足夠空間。
       另一種情況相對(duì)比較“正?!?,就是被轉(zhuǎn)的字符集不包含源字符集的字符,比如utf-8到gb2312的轉(zhuǎn)換就很有可能發(fā)生這種情況。這時(shí)tocode的追加參數(shù)就起作用了,iconv會(huì)自動(dòng)進(jìn)行替換或者忽略。
       如果轉(zhuǎn)換成功(沒(méi)有發(fā)生截?cái)啵?,iconv返回的是不可逆的字符總數(shù)(也就是被替換或是忽略的字符總數(shù),如果一切正常,應(yīng)該返回0),如果轉(zhuǎn)換失敗,返回-1.


3、int iconv_close (iconv_t cd);
釋放句柄資源。

四、utf-8-->gb18030轉(zhuǎn)換示例
    這個(gè)代表了ansi和utf-8或者是ansi之間互相轉(zhuǎn)換的代碼寫法。
  1. <span style="font-size:16px;">iconv_t cd = iconv_open("gb18030//TRANSLIT""<span style="font-family: Georgia; ">utf-8</span>");  
  2. const char* inbuffer; // 輸入源,要轉(zhuǎn)換的字符串  
  3. int srcLen = strlen(inbuffer);  
  4. int outLen = 1024;  
  5. static char s_outbuffer[outLen];  
  6. memset(s_outbuffer, 0, outLen);  
  7. const char* srcStart = inbuffer;  
  8. char* tempOutBuffer = s_outbuffer;//要有這個(gè)臨時(shí)變量,否則iconv會(huì)直接改寫s_outbuffer指針  
  9. size_t ret = iconv(<span style="font-family:Georgia;">cd</span>, (const char**)&srcStart, (size_t *)&srcLen, &tempOutBuffer, (size_t *)&outLen);  
  10. iconv_close(cd);  
  11.   
  12. </span>  

五、unicode->gb18030轉(zhuǎn)換示例
      這個(gè)代表了寬字符和多字節(jié)之間的轉(zhuǎn)換,也就是wchar_t和char之間的轉(zhuǎn)換,也就是WideCharToMultiByte所完成的操作。

  1. FILE* fp = fopen("test-utf16be.txt""rb"); // 文件是unicode文件,這里要用"rb"來(lái)讀取,否則有些字節(jié)等同于EOF文件會(huì)被截?cái)?/span>  
  2. char srcBuffer[1024] = {0};  
  3. fread(srcBuffer, sizeof(srcBuffer) - 1, 1, fp);  
  4.   
  5. // 讀取BOM信息  
  6. // char x[2];  
  7. // fread(&x[0], 1, 1, fp);  
  8. // fread(&x[1], 1, 1, fp);  
  9.   
  10. // 帶有BOM信息,直接用"utf-16";否則應(yīng)該特別指定"utf-16le"或是"utf-16be",這個(gè)要區(qū)分清楚,否則會(huì)出現(xiàn)亂碼  
  11. iconv_t cd = iconv_open("gb18030//TRANSLIT""utf-16");  
  12. int srcLen = 1024;<span style="white-space:pre">    </span>// srcLen和outLen代表的都是字節(jié)數(shù),如果是wchar_t就是字符數(shù)*sizeof(wchar_t)  
  13. int outLen = 1024;  
  14. static char s_outbuffer[outLen];  
  15. memset(s_outbuffer, 0, outLen);  
  16. const char* srcStart = (const char*)srcBuffer;// srcBuffer同樣可以是wchar_t,這里也是這樣強(qiáng)制轉(zhuǎn)換  
  17. char* tempOutBuffer = s_outbuffer;//要有這個(gè)臨時(shí)變量,否則iconv會(huì)直接改寫s_outbuffer指針  
  18. size_t ret = iconv(cd, (const char**)&srcStart, (size_t *)&srcLen, &tempOutBuffer, (size_t *)&outLen);  
  19. iconv_close(cd);  








    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多