什么是字符集缠诅,什么是字符編碼溶浴,它做什么用?
字符(Charcter)是文字與符號(hào)的總稱管引,包括文字士败、圖形符號(hào)、數(shù)學(xué)符號(hào)等汉匙。而字符集是一組抽象的字符組合的集合。如:英文字符集生蚁,中文字符集噩翠,日文字符集等
什么是字符編碼?
計(jì)算機(jī)只能存儲(chǔ)0,1之類(lèi)2進(jìn)制數(shù)字,怎么樣讓它表示那么多各種各樣的字符呢邦投?就需要對(duì)各種字符指定一個(gè)數(shù)值的編碼代號(hào)它就是字符編碼伤锚。如:a這個(gè)字符,在ascii字符集編碼表中對(duì)應(yīng)的編號(hào)是97志衣,而“中”在gb2312字符集中對(duì)應(yīng)的編號(hào)是:16進(jìn)制是D6D0 10進(jìn)制是54992 屯援。通過(guò)編號(hào)就可以找到計(jì)算機(jī)對(duì)應(yīng)字符。不用將那么復(fù)雜的字符保存在計(jì)算機(jī)中念脯,只需要保存它代號(hào)就好狞洋。字符集只是指定了一個(gè)集合中有哪些字符,而字符編碼绿店,是為這個(gè)集合中所有字符定義個(gè)編號(hào)吉懊,這就是字符集與編碼區(qū)別所在。
如果我告訴別人假勿,我這個(gè)字符是:gb2312字符集中編號(hào)是:54992或者是D6D0 借嗽,無(wú)論那個(gè)程序都知道是”中”,如果有人聽(tīng)錯(cuò)了转培,把它弄成日文JIS字符集恶导,然后他也去找編號(hào)是:54992對(duì)應(yīng)的字符,卻找到的是:”面“浸须。
打了這個(gè)比方惨寿,相信大家找到原因了,同樣如果把54992拿到ascii 碼表找删窒,就會(huì)得到對(duì)應(yīng):?? 兩個(gè)不能打印字符了缤沦。
從上面看,當(dāng)你拿到本來(lái)是gb2312編號(hào)易稠,在不是它的字符集里面找就出現(xiàn)這樣問(wèn)題了缸废。 其它,程序出現(xiàn)亂碼也都是這個(gè)原因,找錯(cuò)了字符集表了.
字符在計(jì)算機(jī)是怎么樣存儲(chǔ)的呢企量?
看了上面介紹测萎,我想大家一定會(huì)說(shuō),如果所有文本的字符届巩,都用它的符號(hào)存儲(chǔ)在計(jì)算機(jī)里面硅瞧,不就什么問(wèn)題都么有嗎? 以前也這么想恕汇,后來(lái)一想啊腕唧,如果都存在計(jì)算機(jī)中,各種各樣瘾英,怎么樣表示呢枣接?計(jì)算機(jī)處理01之類(lèi)數(shù)字該多方便呢。
我們可以通過(guò)winhex實(shí)際來(lái)檢查下缺谴,下面在簡(jiǎn)體中文下但惶,將”中按照gb2312字符集編碼保存。
以gb2312編碼保存中文“中”湿蛔,實(shí)際存儲(chǔ)在計(jì)算機(jī)中是:D6D0膀曾,是“中”在字符集gb2312中的編號(hào)啦!
計(jì)算機(jī)中只保存字符在某字符集中對(duì)應(yīng)的字符編號(hào)值阳啥,計(jì)算機(jī)只需要維持一份字符集清單添谊,當(dāng)讀到這種編號(hào)值(編碼),就在對(duì)應(yīng)字符清單中找出該字符顯示出來(lái)即可察迟。字符大小顏色都是程序按照字符樣式繪制而成的碉钠。
看個(gè)圖:
計(jì)算機(jī)中只保存該字符在某字符集中對(duì)應(yīng)的字符編號(hào)(也叫字符編碼)
怎么樣讀取文件并正確顯示文件內(nèi)容?
從上面例子知道字符實(shí)際以該字符在某字符集中字符編碼存儲(chǔ)與計(jì)算機(jī)磁盤(pán)中卷拘。
下面以“中國(guó)”為例(中文簡(jiǎn)體windows):
"中國(guó)"
保存編碼
存儲(chǔ)內(nèi)容
記事本打開(kāi)
ANSI
D6D0 B9FA
正常
gb2312
D6D0 B9FA
正常
utf-8+BOM
EFBBBF E4B8AD E59BBD
正常
utf-8
E4B8AD E59BBD
正常
unicode+BOM
FFFE 2D4E FD56
正常
unicode
2D4E FD56
亂碼(變成ANSI)
EUC-JP
C3E6 B9F1
亂碼(變成ANSI)
iso-8859-1
3F 3F
亂碼(變成ANSI)
以下以:“abc”為例
"abc"
保存編碼
存儲(chǔ)內(nèi)容
記事本打開(kāi)
ANSI
61 62 63
正常
gb2312
61 62 63
正常
utf-8+BOM
EFBBBF 61 62 63
正常
utf-8
61 62 63
正常
unicode+BOM
FFFE 61 62 63
正常
unicode
61 62 63
正常(變成ANSI)
EUC-JP
61 62 63
正常(變成ANSI)
iso-8859-1
61 62 63
正常(變成ANSI)
從上面可以得到幾點(diǎn):
1喊废、以某字符集存儲(chǔ)字符時(shí),它會(huì)在該字符集中搜索這個(gè)字符的位置(編號(hào)或編碼)栗弟,以這個(gè)編號(hào)(編碼)保存在文件污筷,如果所搜找不到該字符,一般會(huì)以:3F 3F保存(一定會(huì)出錯(cuò))
2乍赫、當(dāng)需要顯示字符瓣蛀,從取文件中字符編碼,如果沒(méi)有指定字符集雷厂,會(huì)通過(guò)文件頭(主要unicode字符集有特殊頭標(biāo)記)判斷字符集惋增,如果不是unicode字符集,默認(rèn)都以ANSI字符集讀取改鲫,用字符編碼在該字符集中尋找對(duì)應(yīng)字符诈皿,如果搜索到就正常顯示林束,搜索不到就會(huì)顯示亂碼.
**
**
常見(jiàn)問(wèn)題字符疑問(wèn)收集
什么是ANSI字符集?
這個(gè)不是固定字符集,如果在中文簡(jiǎn)體windows中稽亏,它代碼字符集是gb2312壶冒,在繁體值代表是big5等等。
為什么英文字符不會(huì)出現(xiàn)亂碼截歉?
常見(jiàn)ascii碼字符集是:128字符胖腾,對(duì)應(yīng)編碼值是:1-128 ,二進(jìn)制表示是:00000001-01111111瘪松。它表示了所有常見(jiàn)英文數(shù)字咸作,標(biāo)點(diǎn)符號(hào)。其它字符集都是由ascii碼字符集擴(kuò)展而來(lái)宵睦,擴(kuò)展了最高位由10000000開(kāi)始记罚,用多字節(jié)表示新的字符,基本都保留了:0xxxxxxx 開(kāi)頭128個(gè)基本字符状飞,而且對(duì)應(yīng)編碼與ascii碼相同毫胜。
這樣书斜,常見(jiàn)英文字符不論在那種字符集中诬辈,對(duì)應(yīng)字符編碼一致,存儲(chǔ)編碼也一樣荐吉。讀取時(shí)候無(wú)論用什么字符集讀取焙糟,它所對(duì)應(yīng)字符也一直。所有基本不會(huì)出現(xiàn)亂碼情況样屠。
讀取軟件能夠識(shí)別存儲(chǔ)文件的字符集嗎穿撮?
由于目前各種字符集加起來(lái)有上百種,目前除了unicode字符集痪欲,定義的存儲(chǔ)文件頭悦穿,基本其它字符集只是給出了對(duì)應(yīng)的字符編號(hào)值。因此业踢,相同編號(hào)會(huì)出現(xiàn)在不同的字符集中栗柒,光從文件存儲(chǔ)的編碼值,是不能確定它的字符集的知举。如:gb2312字符集中瞬沦,D6d0對(duì)應(yīng)是“中”,而同樣是:D6D0在ecu-jp 字符集中雇锡,對(duì)應(yīng)是“面”
什么是bom頭逛钻?
bom全稱是:byte order mark,漢語(yǔ)意思是標(biāo)記字節(jié)順序碼锰提。只是出現(xiàn)在:unicode字符集中曙痘,只有unicode字符集芳悲,存儲(chǔ)時(shí)候,要求指定編碼屡江,如果不指定芭概,windows還會(huì)用默認(rèn)的:ANSI讀取。常見(jiàn)的bom頭是:
UTF-8 ║ EF BB BF UTF-16LE ║ FF FE (小尾) UTF-16BE ║ FE FF (大尾) UTF-32LE ║ FF FE 00 00 UTF-32BE ║ 00 00 FE FF
unicode與utf-8 惩嘉、utf-16 utf-32是什么關(guān)系罢洲?
unicode(統(tǒng)一碼、萬(wàn)國(guó)碼文黎、單一碼)是一種字符集惹苗,Unicode是國(guó)際組織制定的可以容納世界上所有文字和符號(hào)的字符編碼方案。Unicode用數(shù)字0-0x10FFFF來(lái)映射這些字符耸峭,最多可以容納1114112個(gè)字符桩蓉,或者說(shuō)有1114112個(gè)碼位。UTF-8劳闹、UTF-16院究、UTF-32都是將數(shù)字轉(zhuǎn)換到程序數(shù)據(jù)的編碼方案。在Unicode中:漢字“字”對(duì)應(yīng)的數(shù)字是23383本涕。我們可以用:UTF-8业汰、UTF-16、UTF-32表示這個(gè)數(shù)字菩颖,將數(shù)字23383存儲(chǔ)在計(jì)算機(jī)中样漆。UTF-8對(duì)應(yīng)是:0xE6, 0xB1, 0x89(3個(gè)字節(jié)),UTF-16對(duì)應(yīng)是:0x6c49(2個(gè)字節(jié)),UTF-32對(duì)應(yīng)是:0x6c49(4個(gè)字節(jié))。utf-8,utf-16,utf-32是unicode碼一種實(shí)現(xiàn)形式晦闰,都是屬于unicode編碼放祟。
unicode編碼特點(diǎn)是什么?
unicode編碼特點(diǎn)是呻右,它定義了編碼方式和存儲(chǔ)實(shí)現(xiàn)方式跪妥。編碼方式就是上面說(shuō)的可以用,utf-8…utf-32表示声滥,而存儲(chǔ)實(shí)現(xiàn)方式眉撵,無(wú)論那種編碼都知道了文件頭(bom)。因此醒串,可以通過(guò)這個(gè)特殊頭來(lái)判斷存儲(chǔ)的文本文件使用那種字符集編碼执桌。
為什么utf-8編碼不指定bom頭(可以理解為文件頭),軟件任然可以正常判斷出它字符集編碼芜赌?
這個(gè)問(wèn)題估計(jì)很多朋友都會(huì)產(chǎn)生疑問(wèn)仰挣,為什么utf-16不指定就讀亂碼,而utf-8可以缠沈。我們可以從下面的例子看下: utf-8是怎么樣從unicode轉(zhuǎn)換而來(lái)了膘壶。
Unicode編碼(16進(jìn)制) ║ UTF-8 字節(jié)流(二進(jìn)制) 000000 - 00007F ║ 0xxxxxxx 000080 - 0007FF ║ 110xxxxx 10xxxxxx 000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx 010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
從上面看错蝴,發(fā)現(xiàn)規(guī)律沒(méi)有?第一個(gè)自己開(kāi)頭有幾個(gè)”1”,后面就對(duì)應(yīng)有幾個(gè)10開(kāi)頭字節(jié)了颓芭。 這樣我們都可以通過(guò)正則進(jìn)行檢測(cè)了.
[\x09\x0A\x0D\x20-\x7E] # ASCII |[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte |\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte |\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates |\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 |[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 |\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
由于它獨(dú)特的編碼存儲(chǔ)特點(diǎn)顷锰,因此目前常見(jiàn)文本處理軟件就能夠自動(dòng)分析出來(lái)。(windows記事本亡问,editplus,notepad++等)
為什么bom頭會(huì)產(chǎn)生亂碼官紫?
有bom頭的存儲(chǔ)或者字節(jié)流,它一定是unicode字符集編碼州藕。到底屬于那一種(utf-8還是utf-16或是utf-32)束世,通過(guò)頭可以判斷出來(lái)。由于已經(jīng)說(shuō)過(guò)utf-16,utf-32不指定bom頭床玻,解析程序默認(rèn)就認(rèn)為是ansi編碼毁涉,出現(xiàn)亂碼。 而utf-8指定或者不指定程序都可判斷知道對(duì)于的字符集編碼锈死。問(wèn)題就出在這里贫堰,可能有的應(yīng)用程序(ie6瀏覽器),它就認(rèn)為如果utf-8編碼待牵,就不需要指定bom頭其屏,它可以自己判斷,相反指定了bom頭洲敢,它還會(huì)出現(xiàn)問(wèn)題(因?yàn)樗杨^當(dāng)utf-8解析出現(xiàn)亂碼了)漫玄。這里不截圖了茄蚯,cnblogs里面談這個(gè)比較多压彭,目前ie6會(huì)出現(xiàn)問(wèn)題。其它ie7+,firefox,chrome不會(huì)出現(xiàn)渗常,會(huì)忽略掉bom頭壮不。 統(tǒng)一解決辦法是:存為utf-8編碼是,不需要加入bom頭皱碘,其它utf-16,utf-32加入询一。
通過(guò)程序運(yùn)算gb2312編碼能夠自動(dòng)轉(zhuǎn)換為utf-8編碼嗎?
utf-8實(shí)際是unicode字符集表現(xiàn)方式癌椿。如果看了這2種字符集編碼表就清楚了健蕊。 它是2個(gè)獨(dú)立字符集,相同漢字在2個(gè)字符集中所對(duì)應(yīng)編號(hào)沒(méi)有關(guān)系踢俄,而且漢字順序也不同缩功,gb2312先按照拼音后按照筆畫(huà)排序,而unicode沒(méi)有做相應(yīng)規(guī)定都办。我們清楚知道嫡锌,如果沒(méi)有對(duì)應(yīng)字符集映射關(guān)系表在手虑稼。通過(guò)直接程序進(jìn)行運(yùn)算是實(shí)現(xiàn)不了的。如果你手里有這2個(gè)字符集映射表势木。如:”字”utf-8是:0xE6, 0xB1, 0x89 蛛倦,對(duì)應(yīng)unicode編碼是:23383,然后拿23383,在unicode字符集尋找啦桌,發(fā)現(xiàn)是字符“字”溯壶,接著將“字”這個(gè)字符,拿到gb2312表中查詢:0xCE,0xC4 因此轉(zhuǎn)換結(jié)果是:0xE6,0xB1,0x89 ---> 0xCE,0xC4甫男。
GB2312茸塞、GBK、gb18030查剖、Big5是什么關(guān)系钾虐?
GB2312:1980年的GB2312一共收錄了7445個(gè)字符,包括6763個(gè)漢字和682個(gè)其它符號(hào)笋庄。漢字區(qū)的內(nèi)碼范圍高字節(jié)從B0-F7效扫,低字節(jié)從A1-FE,占用的碼位是72*94=6768直砂。其中有5個(gè)空位是D7FA-D7FE菌仁。
GBK: 漢字國(guó)標(biāo)擴(kuò)展碼,基本上采用了原來(lái)GB2312-80所有的漢字及碼位,并涵蓋了原Unicode中所有的漢字20902静暂,總共收錄了883個(gè)符號(hào)济丘, 21003個(gè)漢字及提供了1894個(gè)造字碼位。包括港洽蛀、臺(tái)兩種漢字字庫(kù).
GB18030-2000產(chǎn)生摹迷,在GBK漢字標(biāo)準(zhǔn)字符集繼續(xù)擴(kuò)展,GB18030是GBK的超集,也就是包含的字符要比GBK多郊供,又增加了6351個(gè)字符峡碉,其中一部分為4字節(jié)字(four-byte encoding range)。增加了六種少數(shù)民族語(yǔ)言和一些四字節(jié)字驮审。
Big5是中國(guó)臺(tái)灣的鲫寄,是繁體中文代表
GB18030兼容GBK兼容GB2312 ,相同常用漢字在GB2312編碼表中字符編號(hào)(編碼)與GBK,GB18030相同疯淫。如:”字“gb2312字符編碼是:0xCE,0xC4 地来,它在其它2個(gè)里面也是這個(gè)。因?yàn)镚B2312只有7000多常用漢字熙掺,當(dāng)出現(xiàn)繁體未斑,古文時(shí)候就會(huì)出現(xiàn)問(wèn)題,因此采用大集合的GB18030是個(gè)不錯(cuò)選擇适掰。
Big5與GB2312不能通過(guò)程序相互轉(zhuǎn)換颂碧,需要有字符集映射關(guān)系表才能完成荠列。
字符集是怎么樣一個(gè)演變過(guò)程呢?
這個(gè)如果講故事可以講很久了载城。當(dāng)計(jì)算機(jī)有美國(guó)人發(fā)明后肌似,當(dāng)時(shí)設(shè)計(jì)到字符輸入,由于是英文字符诉瓦,通過(guò)收集整理川队。它們形成了標(biāo)準(zhǔn)的ascii碼(128) 字符集。8位睬澡,首位為0固额。 由于不斷普及,歐洲西方國(guó)家相應(yīng)使用煞聪,發(fā)現(xiàn)有些特殊字符它們不能表示斗躏,如:λφ等。如是出來(lái)想法昔脯,想利用ascii碼后128位啄糙,增加它們的字符。這樣就出現(xiàn)了EASCII碼云稚。這些還是不能表示所有國(guó)家隧饼,想法語(yǔ),俄語(yǔ)等有自己特殊字符静陈。因此制定標(biāo)準(zhǔn)將后128位進(jìn)行分片制定燕雁。制定出iso-8859系列字符集。
ISO/IEC 8859-1 (Latin-1) - 西歐語(yǔ)言ISO/IEC 8859-2 (Latin-2) - 中歐語(yǔ)言ISO/IEC 8859-3 (Latin-3) - 南歐語(yǔ)言鲸拥。世界語(yǔ)也可用此字符集顯示拐格。ISO/IEC 8859-4 (Latin-4) - 北歐語(yǔ)言ISO/IEC 8859-5 (Cyrillic) - 斯拉夫語(yǔ)言ISO/IEC 8859-6 (Arabic) - 阿拉伯語(yǔ)ISO/IEC 8859-7 (Greek) - 希臘語(yǔ)ISO/IEC 8859-8 (Hebrew) - 希伯來(lái)語(yǔ)(視覺(jué)順序)ISO 8859-8-I - 希伯來(lái)語(yǔ)(邏輯順序)ISO/IEC 8859-9(Latin-5 或 Turkish)- 它把Latin-1的冰島語(yǔ)字母換走,加入土耳其語(yǔ)字母崩泡。ISO/IEC 8859-10(Latin-6 或 Nordic)- 北日耳曼語(yǔ)支禁荒,用來(lái)代替Latin-4猬膨。ISO/IEC 8859-11 (Thai) - 泰語(yǔ)角撞,從泰國(guó)的 TIS620 標(biāo)準(zhǔn)字集演化而來(lái)。ISO/IEC 8859-13(Latin-7 或 Baltic Rim)- 波羅的語(yǔ)族ISO/IEC 8859-14(Latin-8 或 Celtic)- 凱爾特語(yǔ)族ISO/IEC 8859-15 (Latin-9) - 西歐語(yǔ)言勃痴,加入Latin-1欠缺的芬蘭語(yǔ)字母和大寫(xiě)法語(yǔ)重音字母谒所,以及歐元(€)符號(hào)。ISO/IEC 8859-16 (Latin-10) - 東南歐語(yǔ)言沛申。主要供羅馬尼亞語(yǔ)使用劣领,并加入歐元符號(hào)。
這些在一段時(shí)間铁材,可以解決西方國(guó)家常見(jiàn)字符尖淘。當(dāng)后來(lái)電腦在中日韓等國(guó)家普及時(shí)候奕锌,象中國(guó)常見(jiàn)漢字有7000多個(gè),擴(kuò)展128個(gè)空位村生,完全不夠惊暴。因此,需要用多個(gè)字節(jié)表示趁桃。后來(lái)就定辽话,第一個(gè)字節(jié),第一位如果是1卫病,后面還有一個(gè)字節(jié)與之一起表示一個(gè)字符油啤。如果是0,就對(duì)應(yīng)ascii碼蟀苛。 這樣就形成了國(guó)內(nèi)的gb2312,后來(lái)還是不夠表示繁體中文益咬,加入了:gbk,最后是gb18030,但是帜平,這樣全世界各個(gè)國(guó)家還是用它們自己字符集進(jìn)行表示础废。沒(méi)有一個(gè)統(tǒng)一的大字符集,能夠表示全球所有字符罕模。直到unicode出現(xiàn)评腺,它的設(shè)計(jì)最多可以表示100多萬(wàn)個(gè)字符。全球所有字符都可以收納在其中淑掌。 寫(xiě)出的程序蒿讥,不用經(jīng)常進(jìn)行各種編碼轉(zhuǎn)換。就可以讓世界上所有國(guó)家可以閱讀對(duì)應(yīng)字符文字抛腕。
什么是代碼頁(yè)芋绸,它與字符集有什么關(guān)系?
大家在指定網(wǎng)頁(yè)程序語(yǔ)言生活担敌,還記得cp936表示中文代碼頁(yè)(code page)摔敛。那么它與我們說(shuō)的gbk字符集有什么關(guān)系呢?代碼頁(yè)是字符集編碼的別名全封,也有人稱"內(nèi)碼表"马昙。早期,代碼頁(yè)是IBM稱呼電腦BIOS本身支持的字符集編碼的名稱刹悴。
常見(jiàn)字符集與代碼頁(yè)直接映射是:
cp charset
932 — 日文936 — 簡(jiǎn)體中文(GBK)949 — 韓文950 — 繁體中文(大五碼)1200 — UCS-2LE Unicode 小端序1201 — UCS-2BE Unicode 大端序65001 — UTF-8 Unicode
936就是我們的gbk字符編碼集行楞。
CJK字符集是什么?
cjk代號(hào)意思是:漢語(yǔ)(Chinese)土匀、日語(yǔ)(Japanese)子房、韓語(yǔ)(Korean)。也就是包含這3國(guó)語(yǔ)言的字符集。包含這3個(gè)國(guó)家常見(jiàn)的漢字证杭,一共有2萬(wàn)多個(gè)田度。
所有軟件都會(huì)默認(rèn)是:ANSI字符集嗎?
不同程序默認(rèn)讀取字符集不同解愤,上面舉例是記事本默認(rèn)是這樣的每币。在php里面會(huì)以:iso-8859-1讀取。 jsp程序琢歇,java默認(rèn)字符集也是:iso-8859-1兰怠。
為什么很多軟件程序編譯過(guò)程使用是:iso-8859-1字符集?
由于我們通過(guò)應(yīng)用程序書(shū)寫(xiě)的軟件是用各種字符集編碼保存在磁盤(pán)中李茫。如果中文默認(rèn)是用gbk揭保。保存于磁盤(pán)中,默認(rèn)以字節(jié)碼保存魄宏,是否有無(wú)中文秸侣,每個(gè)字碼值在:1-256。這些剛好可以用iso-8859-1擴(kuò)展單字節(jié)字符集宠互。因?yàn)槲堕唬谴鎯?chǔ)最小單元。在程序語(yǔ)言里面予跌,不會(huì)用中文作變量搏色,函數(shù)等名稱。那些對(duì)應(yīng)都是常見(jiàn)ascii碼券册。而中文用字注釋频轿,或者一些常量中。在編譯時(shí)候不會(huì)影響到語(yǔ)法問(wèn)題烁焙。它會(huì)以原來(lái)字節(jié)碼保持原樣航邢。在讀取時(shí)候,只需要用對(duì)應(yīng)的字符集編碼讀出骄蝇,就能得到對(duì)應(yīng)中文字符膳殷。