ANSI編碼最多見的應用就是在Windows當中的記事本程序中,當新建一個記事本,默認的保存編碼格式就是ANSI,ANSI應該算是一種壓縮編碼了,當遇到標準的ASCII字符時,採用單字節表示,當遇到非標準的ASCII字符(如中文)時,採用雙字節表示。
Unicode編碼標準已在近年來的多種新科技當中被加以採用,包含了可擴展置標語言(XML)、Java程序語言、以及最新的操做系統中。網絡
下面用實驗的方法來進行研究這二者之間的差異:架構
首先要準備的軟件有UltraEdit,用於對文本進行比較;其次用於分析網絡字節序的輔助網站http://bm.kdd.cc/index.asp
編輯器
步入正題,在一個空白的文件夾下建立一個記事本文檔「新建 文本文檔.txt」,在裏面輸入「宋體ABC(回車)」(不包含引號,最後要在ABC後輸入一個回車),保存並關閉該文檔,將此文件選中以後直接複製、粘 貼,在相同的文件夾下就產生了「復件 新建 文本文檔.txt」,再次打開「新建 文本文檔.txt」,選擇菜單中的「文件」->「另存爲」,在另存爲對話框中,最下面有「編碼」,選擇Unicode。保存,選擇替換。網站
然 後打開UltraEdit,在菜單中選擇「文件」->「比較文件」(或直接按快捷鍵Alt+F11),選擇第一個要比較的文件爲「新建 文本文檔.txt」,選擇第二個要比較的文件爲「復件 新建 文本文檔.txt」,「比較模式」選擇文件,「二方比較」,「要比較的第一個文件」爲「二制」,「編輯器平鋪」選擇「垂直平鋪」,點擊「比較」,程序自動 對這兩個文本文件進行比較,並以16進制的形式顯示,以下圖所示:
ANSI編碼:編碼
UNICODE編碼:spa
根據分析,其表明的意義以下圖所示操作系統
在用Unicode對文字進行編碼時,頭兩個字節必定是FF FE,這樣用來標識此文檔以Unicode編碼。下面來關注一下內容的編碼部分:code
中文,做爲一種非ASCII字符,不可能只用一個字節來表示一個漢字,至少須要用兩個字節來表示,因此,中文是一種雙字節字符,下圖所示的是在http://bm.kdd.cc/index.asp上查詢到的「宋體」兩個漢字,分別用Unicode編碼和ANSI編碼的十六進制內容:
ANSI編碼:
文檔
UNICODE編碼:get
在Unicode編碼中,「宋」這個漢字的編碼爲5B 8B,按照二進制的說法,5B是高八位,8B是低八位。然而,對照着前面所標註的結果,用Unicode編碼的文本文件中, 先存儲的是8B這個低八位,而後再存儲的5B這個高八位,這就是Windows內部在處理Unicode字符的時候與其餘系統(如Mac OS)的不一樣,Windows先處理Unicode字符的低八位,而後再處理高八位;而有的系統是先處理高八位,再處理低八位,這就是爲何在 Internet上要規定「網絡字節序」。(2011.3.29 更正:本地字節序處 理順序只與CPU架構有關,與操做系統無關,以前誤覺得Mac OS與Windows不一樣是由於Mac機以前使用的是PPC處理器,該處理器採用大端對齊方式,而從Mac OS 10.4開始出現了支持Intel x86 CPU的系統,這時基於Intel x86架構處理器的Mac機字節序變爲小端對齊。另外,本文中所述Unicode編碼也不嚴謹,應特指爲UTF16編碼。特此更正。)
在ANSI編碼中,徹底不存在這個問題,「宋」的ANSI編碼爲CB CE,在存儲這些字符的時候也是按照先高八位,後低八位的方式存儲的。
以上討論了中文在Unicode和ANSI編碼中的特色,下面看一下ASCII字符在這兩種編碼中的特色:
在Unicode編碼中,全部的字符都是以兩個字節來存儲的(2011.6.22 更正:在UTF-16編碼格式中,並不是全部的字符都是以兩個字節來存儲的。若是僅僅用兩個字節來存儲一個字符,編碼空間爲2^16=65536個,這個數量連中文漢字都包含不全,因此以前的理解有誤差。正確的理解是UTF-16編碼是以兩個字節爲基本編碼單位來存儲的。若是一個字符超出了這兩個字節所能表示的空間,則會再次申請兩個字節來編碼。特此更正。),而ASCII字符僅用一個字節就能夠表示,那麼另一個字節的內容就會被置爲00。採用Unicode會產生的缺點就是:若是一篇文章裏全是英文,那麼,採用Unicode方式編碼存儲,所佔用的存儲空間會大約增長一倍(由於頭部還要多兩個字節的FF FE標識),可是採用Unicode編碼的好處就是適合同一文檔中採用不一樣語言的文字,所以Unicode編碼普遍應用於XML語言(可擴展標記語言)和編寫多語言程序。
在本文的第二組圖中,能夠看到,採用Unicode編碼的大寫英文字母A,其編碼爲00 41(以前曾經解釋了Windows在處理Unicode字符的時候先處理低八位,後處理高八位),由於Unicode存儲的任何字符都佔用2個字節的空間,因此在解碼的時候就兩個字節兩個字節地取。若是發現高八位不是00,則認爲這兩個字節表示一個非ASCII字符,反之若是發現高八位爲00,則可知,該字符爲ASCII字符,因而取出低八位,再根據ASCII碼錶查到對應字符,由於取出的低八位認爲表示的是一個ASCII字符,因此字符空間爲2的8次方,也就是256個,所以採用Unicode編碼表式的ASCII字符屬於擴展的ASCII字符集。
在第二組圖的ANSI編碼解釋中能夠看到,存儲一個大寫英文字母A僅用了一個字節,內容爲41。十六進制的41轉換爲八位的二進制後應該是 01000001,能夠看到,此二進制數的最高位爲0,ANSI編碼在存儲ASCII字符時採用的是傳統的ASCII字符集,其字符數量爲128,正好2的7次方就是128,所以最高位必定是0。漢字「宋」的ANSI編碼爲CB CE,將這兩個字節的十六進制數轉換爲二進制,結果爲[11001011][11001110] ,每一個字節的最高位都是1,由此能夠推斷在解碼的時候,一次讀取一個字節的內容,看一下該字節的最高位是否爲1,若是爲1,暫存該字節,並讀取下一個字節,新讀取的這個字節的最高位應該也爲1,這樣將兩個字節合併而後去查詢對應的字符;若是第一次讀到的一個字節最高位爲0,那麼就按此字節的內容直接查詢傳統的ASCII碼錶,找到對應的字符。
最 後再分析Windows中的回車換行特色。在開始的時候爲了準備這個實驗用的文本文檔,在輸入完ABC後又輸入了一個回車。可是經過分析得知,在文本存儲 的時候並非僅存了一個「回車」,還存了一個「換行」,並且是先存儲的「回車」後存儲的「換行」(見ASCII碼錶:0D->回車;0A-> 換行),這與Linux/Unix中的換行方式不一樣,在Linux/Unix中僅用一個0D(回車)就能夠令文本換行。若是將一個在Linux/Unix 中編寫的文本文檔直接拷貝到Windows中打開(最簡單的能夠在Windows下查看百度首頁的源代碼),就會看到這些文字幾乎都是連着的,沒有換行, 那是由於在該文檔中並沒有顯式地存儲0A(換行符),雖然這篇文章在Linux/Unix中看起來很正常。