字符集編碼(待整理)

http://www.utf8everywhere.org/

http://bbs.chinaunix.net/thread-1230313-1-1.html

========

字符集

就是一個映射表計算機通過它找到對應的字符;unicode的把全球所有文字都做了映射。
utf-8、utf-16、utf-32都是編碼方式。


utf-8利於傳輸因爲它是變長的,有一個字節的(ASCII在utf-8中都只佔一個字節並且是一致的),兩個的,三個的。
有一個傳輸出錯不會影響其他的。如果是固定長度的多字節編碼,少一個字節後面的往前補上,所有的字符編碼都變了,都成亂碼了。
另一個utf-8的好處是字符編碼的每個字節都不會是0x0000(即'\0'),這樣strlen得到的是正確大小,而utf-16和utf-32,如果用char字符串的話,則會有0x0000(標誌結束位)在字符串的非真正結束的地方存在(如果用wchar_t專用的方法處理就會避免這些問題)。
utf-16和unicode的編碼是一樣的。


字符集和實際編碼的聯繫:因爲每個字符和其字符集中的16位二進制碼值是一一對應的,實際編碼只有轉換成相應的字符集對應的16位的unicode碼才能知道它代表哪個字符。關於utf-8和unicode
可以相互轉換。



2.wchar_t                                                                                                                                              
wchar_t正好可以放一個unicode字符,正好就可以輕易的讓它與要顯示的字符對應,也可以用他轉成想要的其他形式的編碼。而如果用char的話,它只有8位,只能一次處理8位的數據,如果將char原封不動的輸出,那用它可以。(用char字符串去做轉換,那可就麻煩了,還要不斷的和前後的char做判斷)。java中char都是2個字節的。


一般在程序中用unicode(utf-16),輸出到文本中都是utf-8,所以輸出前要轉碼。


char *c="我";c字符串的值,一般是utf-8,具體要看你文本編輯器的編碼格式。
而wchar_t wc=L"我";這個是utf-16碼(vs中)。linux中由於wchar_t是4個字節,這個編碼就成了utf-32了。高位基本沒用,16位和unicode編碼一致(linux下沒測試,知道linux下wchar_t是32位,還有utf-32和utf-16低位是一致的)。


將utf-8編碼的unicode字符集放入wchar_t中是不明智的,因爲,這樣wchar_t中可能有兩個字符的編碼,也可能有一個,也可能不到一個,也可能2個半個。


3.其他細節                                                                                                                                          
其他關於UNICODE的字符編具體細節,如utf-8的bom頭,字符序Big Endian、Little Endian等情況可自行查閱資料,我感覺,那些都不是很重要需要的時候查閱就可以,理解概念最關鍵。









寬字節,即 wchar_t 類型採用 Unicode 編碼方式,在 Windows 中爲UTF-16,佔兩個字節的長度,在 Linux 中爲UTF-32,佔四個字節的長度。可以在使用 gcc 編譯程序的時候再後面跟上 -fshort-wchar 來解決這個問題。

wchar_t a = L'a';
wchar_t array[100] = L"Hello world!!!";
    array數組的每個字符都佔16位且是以16位的'\0'結尾。
    字符和字符串前的L通知編譯器應該將其編譯爲Unicode字符串。當編譯器將此字符串放入程序的數據段時,會使用UTF-16來編碼每個字符。


L"我的字符串"表示將ANSI字符串轉換成Unicode字符串。 

strlen("asd")  = 3;  
strlen(L"asd") = 6;


其實使用哪種數據類型並不重要,關鍵是能保持一致性。但程序員無法控制系統中其它部分使用的字符集,所以直接使用Unicode兼容其它字符集最保險。

現在的windows版本內部處理字符串都是使用Unicode字符集,調用windows函數時如果傳入的是一個ANSI字符串,函數首先會執行轉換操作,將ANSI字符串轉換爲Unicode字符串。C運行庫也提供了不同的函數處理不同的字符集,但是與windows不同的是c運行庫的ANSI版本的函數不會在內部調用Unicode版本的函數。


Linux 下 C 標準庫(glib)函數實現 寬字符(wchar_t) 與 多字節字符

http://blog.sina.com.cn/s/blog_4c451e0e0101bl67.html


wchar_t引發的思考

http://www.cnblogs.com/wendao/archive/2012/07/27/2612597.html



一. 各種編碼的來歷

ANSI / ASCII

  編號從0開始的32種狀態分別規定了特殊的用途,一但終端、打印機遇上約定好的這些字節被傳過來時,就要做一些約定的動作。

  遇上00×10,終端就換行,遇上0×07, 終端就嘟嘟叫,遇上0×1b, 打印機就打印反白的字,或者終端就用彩色顯示字母。這些0×20以下的字節狀態稱爲”控制碼”。

  所有的空格、標點符號、數字、大小寫字母分別用連續的字節狀態表示,一直編到了第127號,這樣計算機就可以用不同字節來存儲英語的文字了。

ASCII用0-127的128個數字來代表信息的規範編碼,其中包括33個控制碼,一個空格碼,和94個形象碼。形象碼中包括了英文大小寫字母,阿拉伯數字,標點符號等。人類可閱讀的英文文本就是以形象碼的方式傳遞和存儲的。

電腦中的一個字符大都是用一個八位數的二進制數字表示。這樣每一字符便可能有256個不同的數值。由於美標只規定了128個編碼,剩下的另外128個數碼沒有規範,各家用法不一。另外美標中的33個控制碼,各廠家用法也不盡一致。這樣在不同電腦間交換文件的時候,就有必要區分兩類不同的文件。第一類文件中每一個字都是美標形象碼或空格碼。這類文件叫“文本文件”(ASCII Text Files),通常可在不同電腦系統間直接交換。第二類文件,也就是含有控制碼或非ASCII碼(使用了0到127以外的編碼)的文件,通常不能在不同電腦系統間直接交換。這類文件有一個通稱,叫“二進制文件”(Binary Files)。


  但是很多國家用的不是英文,他們的字母裏有許多是ASCII裏沒有的,所以採用127號之後的空位來表示這些新的字母、符號,還加入了很多畫表格時需要用到的橫線、豎線、交叉等形狀,一直把序號編到了最後一個狀態255。從128到255(0x80~0xFF)的字符集被稱“擴展字符集”。


ANSI

http://baike.baidu.com/subview/185282/6215666.htm


在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼。 不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。 當然對於ANSI編碼而言,0x00~0x7F之間的字符,依舊是1個字節代表1個字符。這一點是ASNI編碼與Unicode編碼之間最大也最明顯的區別。


爲使計算機支持更多語言,通常使用 0x80~0xFF 範圍的 2 個字節來表示 1 個字符。比如:漢字 '中' 在中文操作系統中,使用 [0xD6,0xD0] 這兩個字節存儲。對於ANSI編碼而言,0x00~0x7F之間的字符,依舊是1個字節代表1個字符。這一點是ANSI編碼與Unicode(UTF-16)編碼之間最大也最明顯的區別。比如“A君是第131號”,在ANSI編碼中,佔用12個字節,而在Unicode(UTF-16)編碼中,佔用16個字節。因爲A和1、3、1這4個字符,在ANSI編碼中只各佔1個字節,而在Unicode(UTF-16)編碼中,是需要各佔2個字節的。

當新建文本文檔只輸入“聯通”2字保存再打開時將是亂碼。
當txt文檔中一切字符都在 C0≤AA(第一個字節)≤DF 80≤BB(第二個字節)≤BF 這個範圍時,notepad都無法確認文檔的格式,沒有自動依照UTF-8格式來"Display"。 而"聯通"就是C1 AA CD A8,剛好在上面的範圍內,所以不能正常顯現。
記事本默認是以ANSI編碼保存文本文檔的,而正是這種編碼存在的bug招致了上述怪現象。假如保存時選擇Unicode、Unicode(big endian)、UTF-8編碼就正常了。此外,假如以ANSI編碼保存含有某些特別符號的文本文檔,再次打開後符號也會變成英文問號。


GB2312

  中國把那些127號之後的奇異符號直接取消,規定:一個小於127的字符意義與原來相同,但兩個大於127的字符連在一起時,就表示一個漢字,前一個字節(高字節)從0xA1用到0xF7,後一個字節(低字節)從0xA1到0xFE,這樣可以組合出大約7000多個簡體漢字。

  在這些編碼裏,還把數學符號、羅馬希臘的字母、日文的假名都編進去了,連在 ASCII 裏本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這就是“全角”字符,而原來在127號以下的那些叫”半角”字符。這種漢字方案叫做 “GB2312”,是對 ASCII 的中文擴展。

GB2312編碼範圍是 0xA1A1 - 0xFEFE 

GBK 採用雙字節表示,總體編碼範圍爲 8140-FEFE,首字節在 81-FE 之間,尾字節在 40-FE 之間,剔除 xx7F 一條線。總計 23940 個碼位,共收入 21886 個漢字和圖形符號,其中漢字(包括部首和構件)21003 個,圖形符號 883 個。
編碼分類
1. 漢字區。包括:
a. GB 2312 漢字區。即 GBK/2: B0A1-F7FE。收錄 GB 2312 漢字 6763 個,按原順序排列。
b. GB 13000.1 擴充漢字區。包括:
(1) GBK/3: 8140-A0FE。收錄 GB 13000.1 中的 CJK 漢字 6080 個。
(2) GBK/4: AA40-FEA0。收錄 CJK 漢字和增補的漢字 8160 個。
CJK 漢字在前,按 UCS 代碼大小排列;增補的漢字(包括部首和構件)在後,按《康熙字典》的頁碼/字位排列。
2. 圖形符號區。包括:
a. GB 2312 非漢字符號區。即 GBK/1: A1A1-A9FE。其中除 GB 2312 的符號外,
還有 10 個小寫羅馬數字和 GB 12345 增補的符號。計符號 717 個。
b. GB 13000.1 擴充非漢字區。即 GBK/5: A840-A9A0。BIG-5 非漢字符號、結構符和“○”排列在此區。計符號 166 個。
3. 用戶自定義區:分爲(1)(2)(3)三個小區。
(1) AAA1-AFFE,碼位 564 個。
(2) F8A1-FEFE,碼位 658 個。
(3) A140-A7A0,碼位 672 個。
第(3)區儘管對用戶開放,但限制使用,因爲不排除未來在此區域增補新字符的可能性。

這裏有幾個小技巧:
一、在php中,字符編碼是按所發送的編碼爲準的,因此使用的就是用戶輸入的編碼,不會自動改變,但在asp中,默認的編碼是unicode,這樣我們很容易就能得到gbk->unicode的編碼對照表,這樣即使在毫無基礎庫的情況下也能很容易的實現gbk到utf-8的轉換了;
二、由於GBK是高位最低數值是0x40,即是64,因此,有時候組織一些涉及中文的字串時,分割字符最好用64之前的ascii碼,這樣在任意情況下替換或分割都不會出現亂碼,比較常用的是 ","、";"、":"、" "、" "、" ",這些字符永遠都不會給gb編碼添亂。




“國標”是“中華人民共和國國家標準信息交換用漢字編碼”的簡稱。國標表(基本表)把七千餘漢字、以及標點符號、外文字母等,排成一個94行、94列的方陣。方陣中每一橫行叫一個“區”,每個區有九十四個“位”。一個漢字在方陣中的座標,稱爲該字的“區位碼”。例如“中”字在方陣中處於第54區第48位,它的區位碼就是5448。
其實94這個數字。它是美標中形象碼的總數。國標表沿用這個數字,本意大概是要用兩個美標形象符代表一個漢字。由於美標形象符的編碼是從33到126,漢字區位碼如果各加上32,就會與美標形象碼的範圍重合。如上例“中”字區、位碼加上32後,得86,80。這兩個數字的十六進制放在一起得5650,稱爲該字的“國標碼”,而與其相對應的兩個美標符號,VP,也就是“中”字的“國標符”了。
這樣就產生了一個如何區分國標符與美標符的問題。在一箇中英文混用的文件裏,“VP”到底代表“中”字呢,還是代表某個英文字頭縮寫?電子工業部第六研究所開發CCDOS的時候,使用了一個簡便的解決方案:把國標碼的兩個數字各加上128,上升到非美標碼的位置。(改變後的國標碼,習慣上仍叫“國標”。)
這個方案固然解決了原來的問題,可是新的問題隨之產生。中文文件成了“二進制文件”,既不能可靠地在不同電腦系統間交換,也不與市場上大部分以美標符號爲設計對象的軟件兼容。
爲了區分以上兩種“國標”,我們把原與美標形象碼重合的國標碼稱爲“純國標” ,而把CCDOS加上128的國標碼稱爲“準國標”。
GBK


GBK碼是GB碼的擴展字符編碼,對多達2萬多的簡繁漢字進行了編碼,簡體版的Win95和Win98都是使用GBK作系統內碼。
從實際運用來看,微軟自win95簡體中文版開始,系統就採用GBK代碼,它包括了TrueType宋體、黑體兩種GBK字庫(北京中易電子公司提供),可以用於顯示和打印,並提供了四種GBK漢字的輸入法。此外,瀏覽器IE4.0簡體、繁體中文版內部提供了一個GBK-BIG5代碼雙向轉換功能。此外,微軟公司爲IE提供的語言包中,簡體中文支持(Simplified Chinese Language Support Kit)的兩種字庫宋體、黑體,也是GBK漢字(珠海四通電腦排版系統開發公司提供)。其他一些中文字庫生產廠商,也開始提供TrueType或PostScript GBK字庫。
許多外掛式的中文平臺,如南極星、四通利方(Richwin)等,提供GBK碼的支持,包括字庫、輸入法和GBK與其他中文代碼的轉化器。
互聯網方面,許多網站網頁使用GBK代碼。
但是多數搜索引擎都不能很好的支持GBK漢字搜索,大陸地區的搜索引擎有些能不完善的支持GBK漢字檢索。
其實,GBK是又一個漢字編碼標準,全稱《漢字內碼擴展規範》(Chinese Internatial Code Specification),1995年頒佈。GB是國標,K是漢字“擴展”的漢語拼音第一個字母。
GBK向下與GB-2312編碼兼容,向上支持ISO 10646.1國際標準,是前者向後者過渡的一個承啓標準。
GBK規範收錄了ISO 10646.1中的全部CJK漢字和符號,並有所補充。具體包括:GB 2312中的全部漢字、非漢字符號;GB 13000.1中的其他CJK漢字。以上合計20902個GB化漢字;《簡化總表中》未收入GB 13000.1的52個漢字;《康熙字典》以及《辭海》中未被收入GB 13000.1的28個部首及重要構件;13個漢字結構符;BIG-5中未被GB 2312收入、但存在於GB 13000.1的139個圖形符號;GB 12345增補的6個拼音符號;GB 12345增補的19個豎排圖形符號(GB 12345較GB 2312增補豎排標點符號29個,其中10個未被GB 13000.1收入,故GBK亦不收);從GB 13000.1的CJK兼容區挑選出的21個漢字;GB 13000.1收入的31個IBM OS/2專用符號。GBK亦採用雙字節表示,總體編碼範圍爲0x8140~0xFEFE之間,首字節在0x81~0xFE之間,尾字節在0x40~0xFE之間,剔除0x××7F一條線,總計23940個碼位,共收入21886個漢字和圖形符號,其中漢字(包括部首和構件)21003個,圖形符號883個。




GBK 和 GB18030

  但是中國的漢字太多,不得不繼續把 GB2312 沒有用到的碼位找出來用上。

  後來還是不夠用,於是不再要求低字節一定是127號之後的內碼,只要第一個字節大於127,就表示這是一個漢字的開始,不管後面跟的是不是擴展字符集裏的內容。擴展之後的編碼方案稱爲 GBK,包括了 GB2312 的所有內容,同時又增加了近20000個新的漢字(包括繁體字)和符號。

  後來又加了幾千個新的少數民族的字,GBK 擴爲 GB18030。

  在這個標準裏,最大的特點是兩字節長的漢字字符和一字節長的英文字符並存於同一套編碼方案裏,因此程序爲了支持中文處理,必須要注意字符串裏每一個字節的值,如果這個值大於127的,那麼就認爲這是一個雙字節字符集裏的字符。



CJK碼
ISO-2022是國際標準組織(ISO)爲各種語言字符制定的編碼標準。採用二個字節編碼,其中漢語編碼稱ISO-2022 CN,日語、韓語的編碼分別稱JP、KR。一般將三者合稱CJK碼。CJK碼主要在Internet網絡中使用。


ISO

1993年,國際標準ISO10646 定義了通用字符集(Universal Character Set, UCS)。 UCS 是所有其他字符集標準的一個超集。它保證與其他字符集是雙向兼容的。就是說, 如果你將任何文本字符串翻譯到 UCS格式,然後再翻譯回原編碼, 你不會丟失任何信息。
UCS 包含了用於表達所有已知語言的字符。不僅包括拉丁語,希臘語,斯拉夫語,希伯來語,阿拉伯語,亞美尼亞語和喬治亞語的描述, 還包括中文,日文和韓文這樣的象形文字,以及平假名,片假名,孟加拉語,旁遮普語果魯穆奇字符(Gurmukhi),泰米爾語, 印.埃納德語(Kannada),Malayalam,泰國語, 老撾語, 漢語拼音(Bopomofo), Hangul,Devangari,Gujarati, Oriya,Telugu 以及其它語種。對於還沒有加入的語言, 由於正在研究怎樣在計算機中最好地編碼它們, 因而最終它們都將被加入。這些語言包括Tibetian,高棉語,Runic(古代北歐文字),埃塞俄比亞語, 其他象形文字,以及各種各樣的印-歐語系的語言,還包括挑選出來的藝術語言比如 Tengwar,Cirth 和克林貢語(Klingon)。UCS 還包括大量的圖形的,印刷用的,數學用的和科學用的符號,包括所有由 TeX,Postscript,MS-DOS,MS-Windows, Macintosh, OCR字體, 以及許多其他字處理和出版系統提供的字符。
ISO 10646 定義了一個 31 位的字符集。 然而, 在這巨大的編碼空間中, 迄今爲止只分配了前 65534 個碼位 (0x0000 到 0xFFFD)。這個UCS的16位子集稱爲基本多語言面 (Basic Multilingual Plane, BMP)。 將被編碼在16位BMP以外的字符都屬於非常特殊的字符(比如象形文字), 且只有專家在歷史和科學領域裏纔會用到它們。按當前的計劃, 將來也許再也不會有字符被分配到從0x000000到0x10FFFF這個覆蓋了超過100萬個潛在的未來字符的 21 位的編碼空間以外去了。ISO 10646-1標準第一次發表於1993年, 定義了字符集與 BMP 中內容的架構。定義 BMP以外的字符編碼的第二部分 ISO 10646-2 正在準備中, 但也許要過好幾年才能完成。新的字符仍源源不斷地加入到 BMP 中, 但已經存在的字符是穩定的且不會再改變了。
UCS 不僅給每個字符分配一個代碼, 而且賦予了一個正式的名字。表示一個 UCS 或 Unicode 值的十六進制數, 通常在前面加上 “U+”, 就象U+0041 代表字符“拉丁大寫字母A”。UCS字符U+0000到U+007F 與 US-ASCII(ISO 646) 是一致的, U+0000 到 U+00FF 與 ISO8859-1(Latin-1) 也是一致的。從 U+E000 到 U+F8FF,已經BMP 以外的大範圍的編碼是爲私用保留的。
1993年,ISO10646中定義的USC-4 (Universal Character Set) ,使用了4 個字節的寬度以容納足夠多的相當可觀的空間,但是這個過於肥胖的字符標準在當時乃至21世紀都有其不現實的一面,就是會過分侵佔存儲空間並影響信息傳輸的效率。 與此同時,Unicode 組織於約 10 年前以 Universal, Unique和Uniform 爲主旨也開始開發一個16位字符標準, 爲避免兩種16位編碼的競爭,1992年兩家組織開始協商,以期折衷尋找共同點,這就是今天的 UCS-2 (BMP,Basic Multilingual Plane,16bit) 和Unicode,但它們仍然是不同的方案。
Unicode
關於Unicode我們需要追溯一下它產生的淵源。
當計算機普及到東亞時,遇到了使用表意字符而非字母語言的中、日、韓等國家。在這些國家使用的語言中常用字符多達幾千個,而原來字符采用的是單字節編碼,一張代碼頁中最多容納的字符只有2^8=256個,對於使用表意字符的語言是在無能爲力。既然一個字節不夠,自然人們就採用兩個字節,所有出現了使用雙字節編碼的字符集(DBCS)。不過雙字節字符集中雖然表意字符使用了兩個字節編碼,但其中的ASCII碼和日文片假名等仍用單字節表示,如此一來給程序員帶來了不小的麻煩,因爲每當涉及到DBCS字符串的處理時,總是要判斷當中的一個字節到底表示的是一個字符還是半個字符,如果是半個字符,那是前一半還是後一半?由此可見DBCS並不是一種非常好的解決方案。
人們在不斷尋找這更好的字符編碼方案,最後的結果就是Unicode誕生了。Unicode其實就是寬字節字符集,它對每個字符都固定使用兩個字節即16位表示,於是當處理字符時,不必擔心只處理半個字符。
Unicode在網絡、Windows系統和很多大型軟件中得到應用。


UNICODE

一般情況下說Unicode都是指UTF-16。也就是說每個字符編碼爲兩個字節。

  因爲當時各個國家都像中國這樣搞出一套自己的編碼標準,結果互相之間不兼容,連大陸和臺灣也分別採用了不同的編碼方案:

  當時的中國人想讓電腦顯示漢字,就必須裝上一個“漢字系統”。專門用來處理漢字的顯示、輸入的問題。如果裝臺灣的軟件就必須加裝另一套支持 BIG5 編碼的“倚天漢字系統”纔可以用。裝錯了字符系統,顯示就會亂了套!這怎麼辦?而且世界民族中還有那些暫時用不上電腦的窮苦人民,他們的文字又怎麼辦?

  ISO (國際標誰化組織)決定着手解決這個問題。他們採用的方法很簡單:廢棄所有的地區性編碼方案,重新搞一個包括了地球上所有文化、所有字母和符號的編碼,即 UCS, 俗稱 UNICODE 。( Universal Multiple-Octet Coded Character Set )

  在UNICODE 中,一個漢字不是兩個英文字符。無論是半角的英文字母,還是全角的漢字,都是統一的“一個字符”!同時,也都是統一的“兩個字節”。

UTF-8和UTF-16

字符是可使用多種不同字符方案或代碼頁來表示的抽象實體。例如,Unicode UTF-16 編碼將字符表示爲 16 位整數序列,而 Unicode UTF-8 編碼則將相同的字符表示爲 8 位字節序列。微軟的公共語言運行庫使用 Unicode UTF-16(Unicode 轉換格式,16 位編碼形式)表示字符。

在UTF-8編碼中,一個英文字母字符存儲需要1個字節,一個漢字字符儲存需要3到4個字節。在UTF-16編碼中,一個英文字母字符或一個漢字字符存儲都需要2個字節(Unicode擴展區的一些漢字存儲需要4個字節)。在UTF-32編碼中,世界上任何字符的存儲都需要4個字節。

  UNICODE 如何在網絡上傳輸也是一個必須考慮的問題,於是面向傳輸的衆多 UTF(UCS Transfer Format)標準出現了,顧名思義,UTF8就是每次8個位傳輸數據,而UTF16就是每次16個位。爲了傳輸時的可靠性,從UNICODE到UTF時並不是直接的對應,而是要通過一些算法和規則來轉換。


未來的UCS-4

  如前所述,UNICODE 是用兩個字節來表示爲一個字符,總共可以組合出65535不同的字符,這大概已經可以覆蓋世界上所有文化的符號。如果還不夠也沒有關係,ISO已經準備了UCS-4方案,就是用四個字節來表示一個字符,這樣就可以組合出21億個不同的字符出來(最高位有其他用途)。



編碼種類

字符編碼(Character encoding)是一套法則,使用該法則能夠對自然語言的字符的一個集合(如字母表或音節表),與其他東西的一個集合(如號碼或電脈衝)進行配對。

文字編碼(Text encoding)使用一種標記語言來標記一篇文字的結構和其他特徵,以方便計算機進行處理。

電子編碼(Electronic encoding)是將一個信號轉換成爲一個代碼,這種代碼是被優化過的以利於傳輸或存儲。轉換工作通常由一個編解碼器完成。


利用iconv函數族進行編碼轉換
在LINUX上進行編碼轉換時,既可以利用iconv函數族編程實現,還可以利用iconv命令去實現,只不過後者是針對文件的,也就是將指定文件從一種編碼轉換爲另一種編碼。
iconv函數族的頭文件是iconv.h。有三個函數,原型如下:
(1) iconv_t iconv_open(const char *tocode, const char *fromcode)
此函數說明將要進行哪兩種編碼的轉換,tocode是目標編碼,fromcode是原編碼,該函數返回一個轉換句柄,供以下兩個函數使用。


(2)size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft)
此函數從inbuf中讀取字符,轉換後輸出到outbuf中,inbytesleft用以記錄還未轉換的字符數,outbytesleft用以記錄輸出緩衝的剩餘空間。


(3) int iconv_close(iconv_t cd)
此函數用於關閉轉換句柄,釋放資源。



內碼

http://baike.baidu.com/view/943167.htm


字符編碼

http://baike.baidu.com/view/1204863.htm


代碼頁是字符集編碼的別名,也有人稱"內碼錶"。

http://baike.baidu.com/view/684997.htm




二. 爲什麼有些網站打開有時候會是亂碼

亂碼

亂碼是由於系統或軟件缺乏對某種字符編碼的支持,而產生的不能正常閱讀的混亂字符。常見的內碼錯誤有GB碼和BIG5碼衝突,日文,韓文顯示問題等。

亂碼指的是電腦系統不能顯示正確的字符,而顯示其他無意義的字符或空白。

亂碼是因爲“所使用的字符的源碼在本地計算機上使用了錯誤的顯示字庫”,或在本地計算機的字庫中找不到相應於源碼所指代的字符所致。不同國家和地區的文字字庫採用了相同的一段源碼,或是源文件中因爲文件受到破壞,致使計算機默認提取的源碼錯誤,或是計算機沒有安裝相應字庫,都有可能產生亂碼。


漢字亂碼現象有4種類型:
  1.文本亂碼:是Windows系統顯示亂碼,如:菜單、桌面、提示框等。這是由於OS中有關字體部分的設置不當引起的。
  2.文檔亂碼:是各種應用程序、遊戲本來顯示中文的地方出現亂碼。這種亂碼形成的原因比較複雜,有第1類的亂碼原因,也可能是軟件中用到的中文動態鏈接庫被英文動態鏈接庫覆蓋所造成的;
  3.文件亂碼:主要是指郵件亂碼;
  4.網頁亂碼:是由於港澳的繁體中文大五碼(BIG5)與大陸簡體中文(GB2312)不通用而造成的。
修正亂碼,可以使用轉換工具將系統內碼轉換爲對應內碼,字符即可正確顯示。


產生原因

本質上是因爲涉及的一系列字符處理程序使用的字符集不兼容。
1.一般是軟件程序解碼錯誤。如瀏覽器把GBK碼當成是BIG5碼顯示,或電子郵件程序把對方傳來的郵件錯誤解碼。如果在發送時編碼錯誤,收件者的電郵程序是不能解碼的,需要寄件者的電郵程序重新編碼再寄。例如輸入法是UTF-8字符集,輸入文件時屏幕顯示正常,但該文件採用ANSI編碼,保存時編碼已經被破壞。下次打開該文件,系統顯示程序按該文件的字符集顯示,自然出現亂碼。
2.字體文件(font file)不對。
3.來源編碼錯誤,或文件受到破壞。
4.一種語言版本的操作系統安裝了另外一種語言版本的應用程序,或者應用程序安裝的升級補丁的語言版本與應用程序原來安裝的語言版本不一致。
5.早期單字節的應用程序在打開雙字節語言的文件時不能正確識別文字的分割,在換行的地方把一個字從中分成兩段,導致緊接在後面的整個一行全部都是亂碼。
6.低版本的應用程序不能識別高版本的程序創建的文件。
7.軟件的錯誤操作也會導致整個文件出現亂碼
8.數據庫原因:
1) 數據正確,但數據庫配置錯誤,使用了錯誤的字符集。一般是數據庫移植,還原時DBA的錯誤造成的。
2) 數據正確,但拿到的數據錯誤。一般是客戶端使用了默認的字符集,比如在GBK的機器上開發,但換到Linux下面就出現讀取的數據爲亂碼了。解決方法是,在連接參數裏明確指定數據傳輸用的字符集,而不是使用操作系統默認的。
3) 數據錯誤。一般是客戶端發來的數據編碼問題。比如頁面發送數據是UTF-8,可是後臺處理程序是GBK的,結果造成保存到數據庫的數據爲亂碼。解決方法:所有字符集編碼都採用統一的編碼。比如全部用GBK。




  網頁亂碼是瀏覽器(如IE等)對HTML網頁解釋時形成的。

  如果在瀏覽網站網頁的代碼寫錯語系(比較少見),例如:

<HTML>

<HEAD>

<META CONTENT=“text/html;charset=ISO-8859-1”></HEAD>……

</HTML>

  瀏覽器在顯示此頁時,就會出現亂碼。因爲瀏覽器會將此頁語種辨認爲“歐洲語系”。解決的辦法是將語種“ISO-8859-1”改爲GB2312,如果是繁體網頁則改爲BIG5。

  還有一種可能比較大,就是網頁並沒有標明用的是何種語系,即沒有如下行:

  <META CONTENT=“text/html;charset=XXXXX“>

  而用戶的計算機默認也不是這種語系,比如訪問某些日文網站,經常出現這個問題。主要是由於程序員是面向當地人開發的網站,由於當地都是默認語系,所以沒有亂碼,而用戶是外國人,操作系統本身默認不是當地的語系。所以要手動改語系。


出現口口口口口口這種情況

  這是由於網站並沒有採用UTF-8編碼而是採用的當地的編碼,如蒙古語的,阿拉伯語的編碼,用戶計算機中並沒有這種編碼,所以不能識別。

  解決辦法是,事先爲瀏覽器安裝多語言支持包(例如在安裝IE時要安裝多語言支持包),這樣在瀏覽網頁出現亂碼時,就可以在瀏覽器中選擇菜單欄下的“查看”/“編碼”/“自動選擇”/蒙古),如爲繁體中文則選擇“查看”/“編碼”/“自動選擇”/阿拉伯語,其它語言依此類推選擇相應的語系,這樣可消除網頁亂碼現象。

  三. 目前開發網站用什麼編碼比較好

  我們一般通俗的理解爲:

  UTF-8是世界性通用代碼,也完美的支持中文編碼,如果我們做的網站能讓國外用戶正常的訪問,就最好用UTF-8。

  GB2312屬於中文編碼,主要針對國內用戶使用,如果國外用戶訪問GB2312編碼的網站就會變亂碼。

  網友的反饋一般覺得是用UTF-8比GB2312要多很多,大家都比較贊同用UTF-8。


爲什麼國內幾個網站用GB2312反而更多些呢。

  我也對這個疑問進行了思考,我覺得。應該有3種原因:

  1. 國內這些網站本身歷史也比較長,開始使用的就是 GB2312編碼,現在改成 UTF-8(以前的網頁)轉換的難度和風險太大。

  2. UTF-8編碼的文件比GB2312更佔空間一些,雖然目前的硬件環境下可以忽略,但是這些門戶網站爲了減少服務器負載基本上所有的頁面都生成了靜態頁,UTF-8保存起來文件會比較大,對於門戶級別的網站每天生成的文件量還是非常巨大,帶來的存儲成本相應提高。

  3. 由於UTF-8的編碼比GB2312解碼的網絡傳輸數據量要大,對於門戶級別的網站來說。這個無形之間就要增大帶寬,用GB2312對網絡流量無疑是最好的優化。

  所以在新做站的情況下,建議還是選擇UTF-8比較好。因爲沒有上面那些原因,兼容爲上策。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章