iconv(http://www.gnu.org/software/libiconv/)是一個(gè)開(kāi)源的字符編碼轉(zhuǎn)換庫(kù),可以“方便”的完成幾乎所有的編碼轉(zhuǎn)換工作。說(shuō)簡(jiǎn)單是因?yàn)?,它常用的接口就三個(gè),iconv_open iconv iconv_close,但是即便是只有三個(gè)接口,要想使用正確也不容易。這里把一些基本概念和使用細(xì)節(jié)記錄下來(lái),希望能成為一篇最實(shí)用的入門(mén)教程。
一、字符編碼基本概念
更詳細(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è)漢字。類(lèi)似的,不同的國(guó)家和地區(qū)制定了不同的標(biāo)準(zhǔn),這些使用 2 個(gè)字節(jié)來(lái)代表一個(gè)字符的各種延伸編碼方式,稱(chēng)為 ANSI 編碼。也就是說(shuō),ANSI是一種對(duì)ASCII碼表進(jìn)行擴(kuò)展的泛稱(chēng),不同語(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ǔ)的大寫(xiě)字母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、中文常見(jiàn)編碼: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都是比較常見(jiàn)的編碼方式。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ò)很不常見(jiàn)就是了。
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ī)定:在文本文件的最開(kāi)頭插入幾個(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í)候要先讀文本開(kāi)始的三個(gè)字節(jié)判斷下編碼方式。
二、iconv支持的編碼格式:
uint16_t
or uint32_t
(with machine dependent endianness and alignment)--enable-extra-encodings
, it also provides support for a few extra encodings:1、iconv_t iconv_open (const char* tocode, const char* fromcode);
如果轉(zhuǎn)換編碼不支持(通常是寫(xiě)錯(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表明輸出緩存尚有多少自己剩余。3、int iconv_close (iconv_t cd);
釋放句柄資源。五、unicode->gb18030轉(zhuǎn)換示例
這個(gè)代表了寬字符和多字節(jié)之間的轉(zhuǎn)換,也就是wchar_t和char之間的轉(zhuǎn)換,也就是WideCharToMultiByte所完成的操作。
聯(lián)系客服