JAVA基礎(二)字節 字符 編碼

亂碼或者轉碼,是開發中經常碰到的問題. 理解了編碼到底是怎麼回事,解決起來就會輕鬆很多.

繼續提出問題並解決;

1. 位,字節,字符,編碼,字符集的概念

2.java中的轉碼方式

3.常見亂碼問題


1. 位,字節,字符,編碼,字符集的概念


位(bit):   我們都知道計算機只認識01, 一bit就是這裏的一個0或者1.(二進制的01)

字節(byte): 8個bit構成一個byte,可以表示英語字母,數字(這裏01是十進制的),還可以表示一些符號.是一個很具體的存儲空間.(例如 0x01, 0x45)

字符: 一個或多個字節組合起來代表一個字符.

編碼: 字節組合成字符時,需要一定的規則,這個規則就是編碼方式.(經常看到說1個漢字=2個字節,其實是錯誤的,根據編碼不同,所需字節也不同)

字符集: 字符按編碼規則,能表示出來的字符集合,就是字符集.


各個國家和地區在制定編碼標準的時候,“字符的集合”和“編碼”一般都是同時制定的。因此,平常我們所說的“字符集”,比如:GB2312, GBK, JIS 等,除了有“字符的集合”這層含義外,同時也包含了“編碼”的含義。


下表看下編碼的發展歷史.


系統內碼 說明 系統
階段一 ASCII 計算機剛開始只支持英語,其它語言不能夠在計算機上存儲和顯示。 英文 DOS
階段二 ANSI編碼
(本地化)
爲使計算機支持更多語言,通常使用 0x80~0xFF 範圍的 2 個字節來表示 1 個字符。比如:漢字 '中' 在中文操作系統中,使用 [0xD6,0xD0] 這兩個字節存儲。

不同的國家和地區制定了不同的標準,由此產生了 GB2312, BIG5, JIS 等各自的編碼標準。這些使用 2 個字節來代表一個字符的各種漢字延伸編碼方式,稱爲 ANSI 編碼。在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼。

不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。
中文 DOS,中文 Windows 95/98,日文 Windows 95/98
階段三 UNICODE
(國際化)
爲了使國際間信息交流更加方便,國際組織制定了 UNICODE 字符集,爲各種語言中的每一個字符設定了統一併且唯一的數字編號,以滿足跨語言、跨平臺進行文本轉換、處理的要求。 Windows NT/2000/XP,Linux,Java


然後再用表格來區分下字符,字節的概念:


概念描述 舉例
字符 人們使用的記號,抽象意義上的一個符號。 '1', '中', 'a', '$', '¥', ……
字節 計算機中存儲數據的單元,一個8位的二進制數,是一個很具體的存儲空間。 0x01, 0x45, 0xFA, ……
ANSI
字符串
在內存中,如果“字符”是以 ANSI 編碼形式存在的,一個字符可能使用一個字節或多個字節來表示,那麼我們稱這種字符串爲 ANSI 字符串或者多字節字符串 "中文123"
(佔7字節)
UNICODE
字符串
在內存中,如果“字符”是以在 UNICODE 中的序號存在的,那麼我們稱這種字符串爲UNICODE 字符串或者寬字節字符串 L"中文123"
(佔10字節)

由於不同 ANSI 編碼所規定的標準是不相同的,因此,對於一個給定的多字節字符串,我們必須知道它採用的是哪一種編碼規則,才能夠知道它包含了哪些“字符”。而對於 UNICODE 字符串來說,不管在什麼環境下,它所代表的“字符”內容總是不變的。



2.java中的轉碼方式


在 C++ 和 Java 中,用來代表“字符”和“字節”的數據類型,以及進行編碼的方法:

類型或操作 C++ Java
字符 wchar_t char
字節 char byte
ANSI 字符串 char[] byte[]
UNICODE 字符串 wchar_t[] String
字節串→字符串 mbstowcs(), MultiByteToWideChar() string = new String(bytes, "encoding")
字符串→字節串 wcstombs(), WideCharToMultiByte() bytes = string.getBytes("encoding")

以上需要注意幾點:

1)Java 中的 char 代表一個“UNICODE 字符(寬字節字符)”,而 C++ 中的 char 代表一個字節。

2)MultiByteToWideChar() 和 WideCharToMultiByte() 是 Windows API 函數。



3.常見亂碼問題

其實,理解了編碼是怎麼回事以後,亂碼問題一般都能輕鬆解決.
例如:get傳參,瀏覽器會對參數進行encode,按照什麼編碼進行encode呢?這個就要看瀏覽器自己的設置了.編碼方式不同,後臺就沒法統一decode,所以一般都是開發自己手動指定編碼進行urlencode,後臺再進行統一decode, 這裏還要注意後臺服務器的默認編碼,tomcat默認的iso8859-1,所以一般傳中文參數,都要在server.xml中指定URIEncoding編碼方式.

post傳參時,ContentType裏面會指定編碼,後臺服務器一般會寫個filter,然後調用request.setCharacterEncodingilter來設置編碼.(注意get是這樣設置是不生效的)

最簡單的原則就是所有地方指定相同的編碼.不過總會有例外情況. 當出現亂碼時,先找到是哪個環節出現亂碼,然後對比倆個環節的編碼方式,然後進行適當的轉碼.


參考文章:

http://www.regexlab.com/zh/encoding.htm

http://blog.csdn.net/ygj281583295/article/details/4035386


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