1.字符編碼
編碼:字符(能看懂的)-->字節(看不懂的)
解碼:字節(看不懂的)-->字符(能看懂的)
亂碼:按照A規則存儲,同樣按照A規則解析,那么會顯示正確的文本符號;
反之,按照A規則存儲,再按B規則解析,會導致亂碼現象。
字符編碼(Character Encoding):就是一套自然語言的字符與二進制數之間的對應規則
編碼表:生活中文字和計算機中二進制的對應規則
2.字符集就是編碼表,是系統所有字符的集合,包括各個國家文字、標點符號、圖形符號、數字
等
編碼引發的亂碼問題:
package iotest.bufferedIOtest; /*FileReader在IDEA中默認的編碼格式為UTF-8 * FileReader讀取系統默認編碼(GBK),會出現亂碼 * */ import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; public class ErrorCodeTest { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("C:\\test\\系統默認GBK編碼文本1.txt"); int len =0; while ((len = fr.read()) != -1){ System.out.print((char) len); } fr.close(); } }
運行結果為:
源文件內容為:
亂碼問題解決方法:用轉換流
轉換流的強大之處為:可以指定編碼表(OutputStreamWriter、InputStreamReader可指定特定的編碼表)
GBK編碼中,一個中文占兩個字節
UTF-8編碼中,一個中文占三個字節
OutputStreamWriter 類
java.io.OutputStreamWriter extends writer
OutputStreamWriter:是字符流向字節的橋梁,可使用指定的charset將要寫入流中的字符編碼成字節(編碼:把能看懂的變成看不懂的)
寫在硬盤上的都是字節,當打開文件時,會調用系統的編碼表來解碼
構造方法:
public OutputStreamWriter(OutputStream out, String charsetName)
public OutputStreamWriter(OutputStream out)--默認編碼表為UTF-8
參數:
OutputStream out:字節輸出流,可以把轉換之后的字節寫入到指定文件
String charsetName:指定編碼表名稱,不區分大小寫,utf-8/UTF-8,gbk/GBK都行
使用步驟:
1.創建OutputStreamWriter對象,構造方法中傳遞指定的字節輸出流和指定的編碼表名稱
2.使用OutputStreamWriter的write方法,將字符轉化為字節,存儲在緩沖區中(編碼)
3.使用OutputStreamWriter的flush方法,將內存中的字節寫到硬盤文件中(使用字節流寫的過程)
4.釋放資源
package iotest.changeeachother; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class TestOutputStreamWriter01 { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("C:\\test\\h.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");//編碼表用的是GBK,也可以寫UTF-8 osw.write("你好啊",0,2); osw.write("就你那女女女"); osw.close(); } }
InputStreamReader類
java.io.InputStreamReader extends Reader
InputStreamReader:是字節流向字符的橋梁,可使用指定的charset將要寫入流中的字節編碼成字符
從硬盤上讀取的都是字節,此時編碼表以確定,需要與源文件編碼表相一致
構造方法:
public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in, String charsetName)
參數:
InputStream in:字節輸入流,可以將硬盤上的文件以字節的形式讀取到內存中
String charsetName:指定編碼表名稱,不區分大小寫,utf-8/UTF-8,gbk/GBK都行
使用步驟:
1.創建InputStreamReader對象,構造方法中傳遞指定的字節輸入流和指定的編碼表名稱
2.使用InputStreamReader的read方法,將字節轉化為字符,放在內存中使用(解碼)
3.釋放資源
注意事項
構造方法中的指定的編碼表名稱要與源文件的編碼表名稱相同,否則會出現亂碼
(系統已經按系統的編碼表進行編譯成字節,此時若用不一樣的編碼表,會出現亂碼)
package iotest.changeeachother; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class TestInputStreamReader01 { public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\test\\系統默認GBK編碼文本1.txt"),"utf-8");//源文件使用的編碼表為GBK,而此時設置為utf-8,會出現亂碼 int len = 0; //若設置為GBK,不會出現亂碼 while ((len = isr.read()) != -1){ System.out.print((char) len); } isr.close(); } }
運行結果
練習:轉換文件編碼:將GBK編碼文件轉化為UTF-8編碼的文件
package iotest.changeeachother; import java.io.*; //轉換文件編碼:將GBK編碼文件轉化為UTF-8編碼的文件 public class GBKtoUtf { public static void main(String[] args) throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\test\\GBK文件.txt"),"GBK");//這里必須是GBK OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("C:\\test\\UTF-8文件.txt"),"UTF-8"); int len = 0; while ((len = inputStreamReader.read()) != -1){ outputStreamWriter.write(len); } outputStreamWriter.close(); inputStreamReader.close(); } }