重點:字符串在java(指在JVM中、在內存中)中統一用unicode表示( 即utf-16 LE) , 下面解釋:html
對於 String s = "你好哦!";java
若是源碼文件(java文件)是GBK編碼, 操做系統(windows)默認的環境編碼爲GBK,那麼編譯時, JVM將 按照GBK編碼將字節數組解析成字符(系統文件本質就是二進制流),而後將字符轉換爲unicode格式的字節數組,做爲內部存儲。windows
當打印這個字符串時,JVM 根據操做系統本地的語言環境,將unicode轉換爲GBK,而後操做系統將GBK格式的內容顯示出來。數組
當源碼文件是UTF-8, 咱們須要通知編譯器源碼的格式,javac -encoding utf-8 ... , 編譯時,JVM按照utf-8 解析成字符,而後轉換爲unicode格式的字節數組, 因此不論源碼文件是什麼格式,一樣的字符串,最後獲得的unicode字節數組是徹底一致的,顯示的時候,也是轉成GBK來顯示(跟OS環境有關:OS表示操做系統)tomcat
例如:this
String s = "你好哦!";編碼
System.out.println( new String(s.getBytes(),"UTF-8")); //錯誤,由於getBytes()默認使用GBK編碼, 而解析時使用UTF-8編碼,確定出錯。spa
其中 getBytes() 是將unicode 轉換爲操做系統默認的格式的字節數組,即"你好哦"的 GBK格式,操作系統
new String (bytes, Charset) 中的charset 是指定讀取 bytes 的方式,這裏指定爲UTF-8,即把bytes的內容當作UTF-8 格式對待。code
以下兩種方式都會有正確的結果,由於他們的源內容編碼和解析用的編碼是一致的。
System.out.println( new String(s.getBytes(),"GBK"));
System.out.println( new String(s.getBytes("UTF-8"),"UTF-8"));
網上流傳着一種錯誤的方法:
GBK--> UTF-8: new String( s.getBytes("GBK") , "UTF-8); ,這種方式是徹底錯誤的,由於getBytes 的編碼與 UTF-8 不一致,確定是亂碼。
可是爲何在tomcat 下,使用 new String(s.getBytes("iso-8859-1") ,"GBK") 卻能夠用呢? 答案是:
tomcat 默認使用iso-8859-1編碼, 也就是說,若是本來字符串是GBK的,tomcat傳輸過程當中,將GBK轉成iso-8859-1了,
默認狀況下,使用iso-8859-1讀取中文確定是有問題的,那麼咱們須要將iso-8859-1 再轉成GBK, 而iso-8859-1 是單字節編碼的,
即他認爲一個字節是一個字符, 那麼這種轉換不會對原來的字節數組作任何改變,由於字節數組原本就是由單個字節組成的,
若是以前用GBK編碼,那麼轉成iso-8859-1後編碼內容徹底沒變, 則 s.getBytes("iso-8859-1") 實際上仍是原來GBK的編碼內容
則 new String(s.getBytes("iso-8859-1") ,"GBK") 就能夠正確解碼了。 因此說這是一種巧合。
String gbkStr = "你好哦!"; //源碼文件是GBK格式,或者這個字符串是從GBK文件中讀取出來的, JVM會把字符轉化成unicode格式
//利用getBytes將unicode字符串轉成UTF-8格式的字節數組
byte[] utf8Bytes = gbkStr.getBytes("UTF-8");
//而後用utf-8 對這個字節數組解碼成新的字符串
String utf8Str = new String(utf8Bytes, "UTF-8");
簡化後就是:
unicodeToUtf8 (String s) {
return new String( s.getBytes("utf-8") , "utf-8");
}
UTF-8 轉GBK原理也是同樣
return new String( s.getBytes("GBK") , "GBK");
其實核心工做都由 getBytes(charset) 作了。
getBytes 的JDK 描述:Encodes this String into a sequence of bytes using the named charset, storing the result into a new byte array.
另外對於讀寫文件,
OutputStreamWriter w1 = new OutputStreamWriter(new FileOutputStream("D:\\file1.txt"),"UTF-8");
InputStreamReader( stream, charset)
能夠幫助咱們輕鬆的按照指定編碼讀寫文件。