纯文本文件的字符编码未声明_浅谈几种常见的字符编码
引子
相信大家平時(shí)工作和生活中,都遇到過(guò)亂碼的現(xiàn)象。比如PDF格式的文件復(fù)制粘貼到Word文件中,很容易出現(xiàn)錯(cuò)誤,影響對(duì)文件的識(shí)別。那么這種現(xiàn)象是如何產(chǎn)生的呢?下面就帶大家一探究竟。
ASCII
最早廣泛使用,名氣最大的編碼方式當(dāng)屬ASCII(美國(guó)標(biāo)準(zhǔn)信息交換碼)。眾所周知,計(jì)算機(jī)內(nèi)部的所有信息最終都是一個(gè)二進(jìn)制值。每一個(gè)二進(jìn)制位(bit)有0和1兩種狀態(tài),因此八個(gè)二進(jìn)制位就可以組合出256種狀態(tài),這也被稱為一個(gè)字節(jié)(byte)。也就是說(shuō),一個(gè)字節(jié)可以表示256種不同的狀態(tài),每一個(gè)狀態(tài)對(duì)應(yīng)一個(gè)符號(hào),就是256個(gè)符號(hào)。
ASCII碼由一張主表和一張擴(kuò)展表組成,如下圖,圖源網(wǎng)絡(luò)。
使用WinHEX以16進(jìn)制打開(kāi)內(nèi)容為“AB”的ASCII編碼方式的文本文件,可以看到其值為0x41、0x42對(duì)應(yīng)十進(jìn)制的65、66,符合上表內(nèi)容。
ASCII碼表對(duì)于以英語(yǔ)為母語(yǔ)的國(guó)家來(lái)說(shuō),足夠用了。但對(duì)于其他國(guó)家來(lái)說(shuō),明顯是不能滿足需求的。所以,在計(jì)算機(jī)傳入中國(guó)以后,中國(guó)專家制定了GB2312/GB2312-80編碼。
中文字符編碼
GB2312/GB2312-80
由于擴(kuò)展ASCII碼表不常用,中國(guó)專家整合了擴(kuò)展ASCII碼表(即128-255)并進(jìn)行了重新編碼,規(guī)定:一共小于127的字符的意義與原來(lái)相同,但當(dāng)兩個(gè)大于127的字符連在一起時(shí),就表示一個(gè)漢字,這樣我們就可以組合出大約7000個(gè)簡(jiǎn)體漢字。上述編碼規(guī)則就是GB2312或GB2312-80(國(guó)標(biāo)碼)。
經(jīng)過(guò)對(duì)本來(lái)ASCII里就有的數(shù)字、標(biāo)點(diǎn)、字母進(jìn)行兩個(gè)字節(jié)場(chǎng)的重新編碼,就形成了常說(shuō)的"全角"字符,而原來(lái)小于127號(hào)的那些就叫"半角字符"。
使用WinHEX以16進(jìn)制打開(kāi)內(nèi)容為“AB中國(guó)”的GB2312編碼方式的文件,可以清楚的看到A、B仍然存儲(chǔ)為0x41、0x42;“中”和“國(guó)”均由2個(gè)處于0x80-0xFF的十六進(jìn)制數(shù)(對(duì)應(yīng)十進(jìn)制的128-255)表示。
GB2312/GB2312-80包含了大部分常用漢字。然而在生產(chǎn)生活中,我們時(shí)不時(shí)的會(huì)使用到一些生僻字,在此基礎(chǔ)上就誕生了GBK編碼。
GBK
GB2312支持的漢字太少。1995年的漢字?jǐn)U展規(guī)范GBK1.0收錄了21886個(gè)符號(hào),它分為漢字區(qū)和圖形符號(hào)區(qū)。其中漢字區(qū)包括21003個(gè)字符。
從ASCII、GB2312到GBK,這些編碼方法是向下兼容的,即同一個(gè)字符在這些方案中總是有相同的編碼,后面的標(biāo)準(zhǔn)支持更多的字符。在這些編碼中,英文和中文可以統(tǒng)一處理。字符不論中英文均使用雙字節(jié)來(lái)表示,只不過(guò)為了區(qū)分中文,才將其最高位都定成1。
由于GBK與GB2312和SCII編碼兼容,所以在常用字符上,二者編碼一致,為避免重復(fù),此處不在圖上詳細(xì)講解。
GBK編碼很好地滿足了我們國(guó)家民眾的需求,但這種方式也有其弊端。如跨國(guó)交流的時(shí)候,像中國(guó)和日本、韓國(guó)等使用象形文字的國(guó)家之間,傳送文件后仍會(huì)出現(xiàn)亂碼現(xiàn)象。在此種情況下,Unicode應(yīng)運(yùn)而生。
UNICODE
Unicode是一個(gè)編碼方案,說(shuō)白了就是一張包含全世界所有文字的一個(gè)編碼表,只要這個(gè)世界上存在的文字符號(hào),統(tǒng)統(tǒng)給你一個(gè)唯一的編碼。Unicode編碼范圍是: 0-0x10FFFF,可以容納100多萬(wàn)個(gè)符號(hào)。
Unicode其實(shí)更像是一個(gè)符號(hào)集,它只規(guī)定了符號(hào)的二進(jìn)制代碼,卻沒(méi)有規(guī)定這個(gè)二進(jìn)制代碼應(yīng)該如何存儲(chǔ)。
Unicode 編碼共有三種具體實(shí)現(xiàn),分別為UTF-8,UTF-16,UTF-32。我們平時(shí)所說(shuō)的Unicode 編碼默認(rèn)是指UTF-16編碼。
UTF-16
UTF-16編碼以16位無(wú)符號(hào)整數(shù)為單位,注意是16位為一個(gè)單位,不能一股腦地認(rèn)為UTF-16編碼就是16位;這個(gè)要看字符的unicode編碼處于什么范圍而定,有可能是2個(gè)字節(jié),也可能是4個(gè)字節(jié)。
同樣以內(nèi)容為“AB中國(guó)”的文本文件為例,最前面的“FF FE”被稱為BOM,這個(gè)下文會(huì)提到,先不談。可以看到即便是A、B這種原本只用一個(gè)字節(jié)能表示的字符,也仍舊占據(jù)了兩個(gè)字節(jié)。
在本地還好,只是浪費(fèi)點(diǎn)磁盤空間,但是在網(wǎng)絡(luò)傳輸時(shí),十分占用資源,尤其對(duì)英語(yǔ)母語(yǔ)的國(guó)家而言。
UTF-32
UTF-32是對(duì)Unicode編碼的最簡(jiǎn)單粗暴的實(shí)現(xiàn)方式,即每個(gè)字符均有4個(gè)字節(jié)表示。UTF-16尚且算浪費(fèi)資源,更何況UTF-32呢?由于其過(guò)于浪費(fèi)資源,使用范圍很窄,本文在這里就不詳談了。
那么有沒(méi)有一種比較省資源的編碼方式呢?答案是有,即UTF-8編碼。
UTF-8
UTF-8是一種非常靈活的編碼方式,其根據(jù)字符在Unicode編碼中的位置來(lái)決定其由幾個(gè)字節(jié)組成。對(duì)應(yīng)關(guān)系如下表:
| 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 |
同樣以內(nèi)容為“AB中國(guó)”的文本文件為例,最前面的“EF BB BF”被稱為BOM,先忽略。字符A、B處在000000 - 00007F范圍內(nèi),所以仍為0x41、0x42,很容易理解。難點(diǎn)在"中"和"國(guó)“的編碼。
以”中“為例,“中”的Unicode編碼為4E 2D,處于000800 - 00FFFF范圍內(nèi)。將4E 2D化為二進(jìn)制“0100 ?1110 ?0010 ? 1101”,按照上表中第三行右側(cè)的情況分組,然后在最前面填充“1110”、“10”、”10“,最后在重新轉(zhuǎn)成16進(jìn)制即可。“國(guó)”同理,由興趣的讀者可以嘗試推導(dǎo)下。
4 E 2 D 0100 1110 0010 1101 0100 111000 10110111100100 10111000 10101101 E4 B8 AD因?yàn)閁TF-8編碼方式靈活,所以相應(yīng)的其解碼所需的時(shí)間也比UTF-16和UTF-32要長(zhǎng)。
BOM
BOM(Byte Order Mark),字節(jié)順序標(biāo)記,出現(xiàn)在文本文件頭部,Unicode編碼標(biāo)準(zhǔn)中用于標(biāo)識(shí)文件是采用哪種格式的編碼。
以UTF-16和UTF-8為例:
| 編碼格式 | 文件起始標(biāo)識(shí) |
| UTF-8 | EF BB BF |
| UTF-16LE(小端存儲(chǔ)) | FF FE |
| UTF-16BE(大端存儲(chǔ)) | FE FF |
大端存儲(chǔ)和小端存儲(chǔ)
?概念
大端存儲(chǔ)與小端存儲(chǔ)模式主要指的是數(shù)據(jù)在計(jì)算機(jī)中存儲(chǔ)的兩種字節(jié)優(yōu)先順序。
?小端存儲(chǔ):高位字節(jié)放在高地址,低位字節(jié)存放在低地址。?大端存儲(chǔ):高位字節(jié)放在低地址,低位字節(jié)存放在高地址。
例如要表示0x12345678
偏移地址: 0x 00 01 02 03小端存儲(chǔ): 78 56 34 12大端存儲(chǔ): 12 34 56 78?各自優(yōu)點(diǎn):?小端存儲(chǔ):便于數(shù)據(jù)之間的類型轉(zhuǎn)換,例如:long類型轉(zhuǎn)換為int類型時(shí),高地址部分的數(shù)據(jù)可以直接截掉。?大端存儲(chǔ):便于數(shù)據(jù)類型的符號(hào)判斷,因?yàn)樽畹偷刂肺粩?shù)據(jù)即為符號(hào)位,可以直接判斷數(shù)據(jù)的正負(fù)號(hào)。?用途:?小端存儲(chǔ):常見(jiàn)于本地主機(jī)上(也有部分類型主機(jī)為大端存儲(chǔ))和x86平臺(tái)。?大端存儲(chǔ):常見(jiàn)于網(wǎng)絡(luò)通信和arm/移動(dòng)平臺(tái)上,網(wǎng)際協(xié)議TCP/IP在傳輸整型數(shù)據(jù)時(shí)一般使用大端存儲(chǔ)模式表示,例如TCP/IP中表示端口和IP時(shí),均采用的是大端存儲(chǔ)
工具推薦
?WinHEX:http://www.x-ways.net/winhex/?UltraEdit:https://www.ultraedit.com/?CyberChef: https://github.com/gchq/CyberChef
總結(jié)
盡管編碼方式多種多樣,現(xiàn)實(shí)生活中仍需靈活選擇。若選擇國(guó)際通用,則選擇UTF-8編碼;若僅僅是國(guó)內(nèi)使用,則選擇GBK編碼(因?yàn)閁TF-8中漢字占了3個(gè)字節(jié),反而浪費(fèi)了空間)。其他編碼,可以自取所需。
此外,若遇到亂碼問(wèn)題,可以使用Windows平臺(tái)內(nèi)置的記事本notepad.exe.打開(kāi)文件后,點(diǎn)擊文件菜單中的“另存為命令”,點(diǎn)擊對(duì)話框最底部編碼的下拉條,保存即可。
總結(jié)
以上是生活随笔為你收集整理的纯文本文件的字符编码未声明_浅谈几种常见的字符编码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python打开文件报错无效序列_psy
- 下一篇: 无聊的python课程_无聊的钢镚的py