java io亂碼怎麼辦? java中IO及中文亂碼問題
第一次發這種博客,所以一直在糾結怎麼開頭,乾脆直奔主題吧,把自己的一些總結體會記錄下來,先從簡單的學習開始,希望可以慢慢堅持,以後的內容可以寫的更好更有意義。
其實真正在工作中中文亂碼的問題遇到的不多,那是因為公司為了開發方便所以文件都統一編碼了。但是我覺得還有很有必要去稍微了解一下其原理的。
推薦:《java學習》
IO就是輸入輸出流,用物件導向來理解的話,就是輸入,輸出流對象,主要用來操作文件物件。所以再稍微談談文件的概念,即File物件。在Java中,File不是我們平常生活中指的某個具體文件,而是某個路徑對象,比如說File file=new File("D:\\aaa"); 這是一個File對象,也許它表示的是一個資料夾,也許這個路徑都不存在,但這句程式碼就的確確建立了一個表示該路徑的File物件。這種寫法只是不常用罷了。因為我們平常可能更多的是操作一個文本,圖片等等,如File f=new File("aaa.txt");
上面簡單說了IO,File是什麼,接下來再談談這些圖片,文字,影片等資訊是如何保存在我們儲存裝置上的。
個人理解是不管是什麼類型的文件,都是二進位的形式保存,最小單位是1個byte,即8位01組成。所以說我們假如要拷貝一個文件,只要操作位元組流就好了,即把一個文件中的所有字節拿到,寫到另一個文件中就OK了,其實理論上是可以的,但是對於字符型的文件比較特殊。
這也就是為什麼會有中文亂碼的問題出現。 ASCII碼表大家都很熟悉,起碼都聽說過,它應該算是很早出現的一種碼表了吧,起初只是用來表示26個英文字母和一些特殊符號(因為計算機只識別二進制,所以要把字元用對應的位元組來代替,形成一張碼表)。
但隨著電腦的發展,ASCII應該不夠用了吧,而且很多國家應該也都有自己的一套編碼方案,所以就出現了不同的編碼表。常見的有GBK,UTF-8,而jvm中預設使用的是unicode編碼,即以2個位元組表示一個漢字,UTF-8則不一定,可能3個位元組表示一個漢字,也可能更多。所以就出現了一個問題,同一個漢字在不同的碼表中對應的字節碼的個數和內容都不相同。
所以要如何解決?
我們從A磁碟上拷貝一張圖片到B磁碟上,只要把A的所有位元組拿到B就可以了。但是同樣的方式操作一個文字其實也是可以的,前提是A和B中的文字編碼要相同。因為圖片不存在位元組編碼的問題。但是我要從網路上或伺服器去傳輸中文怎麼辦呢,肯定不能單單通過字節來實現了(因為我們不可能遇到問題就手動去更改文件的編碼方式吧)。所以java提供了字元流對象,也就是在位元組流的基礎上加上對編碼的設置,達到解決亂碼的問題。
廢話不多說,用幾個小案例來說明一下:
1,先在目前專案下新建aa.txt,bb.txt。隨便在aa中寫幾個中文字。會發現這兩種方式都可以實現
a,採用字元流
FileReader fr=new FileReader("aa.txt"); FileWriter fw=new FileWriter("bb.txt"); int c; while((c=fr.read())!=-1){ fw.write(c); } fr.close(); fw.close();
b,採用位元組流
FileInputStream fis=new FileInputStream("aa.txt"); FileOutputStream fos=new FileOutputStream("bb.txt"); int b; while((b=fis.read())!=-1){ fos.write(b); } fis.close(); fos.close();
2,此時假如aa的編碼方式是UTF-8的話,那我們把bb的編碼改為GBK看看,同樣運行上面兩種方法,全部亂碼。
原因就是因為兩個檔案的編碼方式不同,導致中文查的碼表不同,所以亂碼。
3,所以當兩邊檔案的編碼方式不同,我們可以在讀取和寫入的時候都指定與其檔案對應的編碼即可。
實作方式如下:
InputStreamReader isr=new InputStreamReader(new FileInputStream("aa.txt"),"utf-8"); OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("bb.txt"),"gbk"); char[] arr=new char[1024]; int len; while((len=isr.read(arr))!=-1){ String s=new String(arr,0,len); System.out.println(s); osw.write(s); } isr.close(); osw.close();
程式碼雖然很簡單,還是簡單的解釋一下,從API可以發現InputStreamReader和OutputStreamWriter都是操作字元的對象,繼續Reader和Writer。
主要用來把位元組轉成字符,字符轉成字節。所以從構造也可以發現,傳入的是位元組流物件。以utf-8去讀取位元組流轉成字符,然後將字符以gbk編碼轉成位元組寫入。
下面幾行就不做解釋了,都是基礎裡面的方法。構造中傳入的是匿名內部類別對象,還有裝飾設計模式,這種寫法簡單了解下即可。
關於位元組流和字元流其實還有很多很好用的類,像是BufferedInputStream,BufferedReader等等,再次不做贅述。
關於jvm和系統平台的編碼問題,在次不做解釋。
可以用String來嘗試一下,觀察字串在編譯和執行時的字節碼及編碼問題。
以上是java io亂碼怎麼辦的詳細內容。更多資訊請關注PHP中文網其他相關文章!