下面解釋一下Java的編碼方式,知道了編碼方式則亂碼將很容易解決。
1:java中byte是以補碼表示:http://www.tkk7.com/orangelizq/archive/2008/07/20/216228.html
2 : IO流操作的基本單元
觀看io里面stream的操作,最終有兩種:write(int b),write(byte[] bs),讀的方式也一樣。 其余的均是在這兩種方式上進行封裝處理。
由此也能看到文件操作的基本單元bit,而Java的基本單元是字節(byte),一個字節8個bit,字節能表示的范圍為[0,255]。而java里面的byte類型的范圍是[-128,127],這點必須區分開。
因此對write(b), write(byte[] bs) 的理解應該以bit的方式去理解,不能以Java中的byte類型去理解。
OutputStream.write(int b)是將一個字節寫入到流中,而不是將int寫入流中,即將int所表示的低8位bit寫入,高24bit舍去。因此通過write(int b)將一個byte類型的b寫入時不會有問題的:
byte b = (byte)-1;out.write(b); 該轉化過程為: btye -> int ->
截取低8位,寫入流中。
中間byte->int得到的int的bit序列可能有誤,具體請看:http://www.tkk7.com/orangelizq
/archive/2008/07/20/216228.html, 但由于最后截取低8位bit,所以最后得到的bit都是正確的。
同樣可以推理出int i = read() 和 byte b =(byte)read(); 由此我們可以看到讀寫進行的bit處理都是一致的。
使用IO的這些接口時,不用考慮是int 還是byte類型,直接調用即可。
3: byte,unicode, 編碼方式(比如UTF8)之間的關系
unicode 和utf8的關系: http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
Java編碼的基本概念:Java采用的編碼:unicode,JVM平臺默認字符集和外部資源的編碼
請參閱: http://www.javaeye.com/topic/311583
Java中String 是以unicode的方式存儲,也就是說一個String的unicode編碼是固定的,其unicode表示的byte序列也是固定。
由于存儲效率的原因,我們需要使用別的編碼方式,比如utf8,那么就需要將unicode的bit序列轉化為utf8所表示的bit序列,這要求unicode和utf8之間必須能互相轉換。
因此可以得出:對同一個unicode使用不同的編碼方式得到的bit序列將是不一樣的。
4:亂碼的問題:
一般的數據流程:外部輸入 -> Java String -> 外部輸出。
由于IO處理的byte(8個bit)類型,因此該流程應該為:讀取外部介質-> 輸入的byte序列 ->JVM的unicode -> 輸出的byte序列 -> 寫到到外部介質
因此亂碼的問題,就會出現在兩個地方: 輸入的byte序列 -> JVM的Unicode 和 JVM的unicode ->輸出byte序列
也就是, 將某中編碼的byte序列 轉為 unicode 和 將unicode 轉化為 某種編碼的byte序列。
如果你不知道是哪種編碼和unicode進行互轉,比如:將UTF8的byte序列使用GBK的編碼方式轉化為unicode,那么得到unicode byte序列可能不對,則在unicode字符集中找到字符和原來就很可能千差萬別了。
另外通過new String(byte[] bs)是不指定編碼方式,則默認使用jvm的字符編碼進行處理。 因此http://www.javaeye.com/topic/311583 指出一定要知道外部系統和JVM的編碼方式。
posted on 2010-09-02 13:58
南國咖啡 閱讀(1717)
評論(0) 編輯 收藏