天天看點

位元組流(InputStream)輸入中文漢字到控制台出現亂碼的問題解析

1、了解為什麼InputStream輸入中文到控制台會出現亂碼的關鍵,是要弄清楚亂碼根源。

2、GBK每個漢字兩個位元組,UTF-8每個漢字三個位元組,假如在接收一個中文字元時,隻接收了中文字元的一個位元組就開始輸出,那麼那個中文字元就會失幀,是以就會亂碼。

3、如果是輸出到指定檔案,就不用擔心此問題,因為檔案都是全部接收完畢後才打開新生成的檔案。是以就保證了資料的全部接收。

4、代碼示範如下:

package com.tiger.practice;

import java.io.*;
/**
 * FileInputStream 輸入中文到控制台出現亂碼的原因解析
 * @author tiger
 * @Date 2017年7月22日
 */
public class ShowConsole {
	public static void main(String[] args) throws IOException {
		String path = "E:\\tigerFolder\\FileInputStream.txt";
		System.out.println("1、-------FileInputStream輸入中文出現亂碼-------");
		test01(path);
		System.out.println("\n2、-----解決FileInputStream輸入中文出現亂碼----\n");
		test02(path);
		System.out.println("\n3、---------FileReader輸入------------\n");
		test03(path);
		System.out.println("\n4、-------利用轉換流包裹位元組流輸入-----\n");
		test04(path);
		System.out.println("\n5、-在test04的基礎上加增強緩沖流,加快讀取速度-\n");
		test05(path);

	}
	/*
	 * 情況一:位元組流輸入 FileInputStream ,中文出現亂碼,這裡沒有解碼。
	 */
	public static void test01(String path) throws IOException{
		InputStream is = new FileInputStream(path);
		int len = 0;
		while ((len = is.read()) != -1) {
			System.out.print((char)len);
		}
		is.close();
	}
	/*
	 * 情況二:位元組流輸入 FileInputStream ,解決中文出現亂碼問題
	 */
	public static void test02(String path) throws IOException{
		InputStream is = new FileInputStream(path);
		int len = 0;
		/*将檔案資料全部接收到數組buffer中,再控制台輸出,保證了接收的中文位元組數不會失幀。
		GBK每個漢字兩個位元組,而UTF-8每個漢字三個,假如在接收一個中文字元時,
		隻接收了中文字元的一個位元組就開始輸出,那麼那個中文字元就會失幀,是以就會亂碼*/
		byte[] buffer = new byte[is.available()];
		while ((len = is.read(buffer)) != -1) {
			System.out.print(new String(buffer,0,len));
		}
		is.close();
	}
	/*
	 * 情況三:字元流輸入 FileReader 繼承了 InputStreamReader,
	 * 每次都是接收兩個位元組,是以中文(占兩個位元組)絕不會亂碼。
	 * 但要注意讀取的文本的編碼格式要與源程式的解碼格式一緻。
	 */
	public static void test03(String path) throws IOException{
		Reader reader = new FileReader(path);
		int len = 0;
		char[] cbuf = new char[1024];//緩沖
		while ((len = reader.read(cbuf)) != -1) {
			System.out.print(new String(cbuf,0,len));
		}
	}
	/*
	 * 情況四:利用轉換流,将位元組流轉換為字元流(InputStreamReader)包裹位元組流輸入[内建緩沖區,8192個位元組,
	 具有預讀功能],改變其解碼方式(可以自由設定解碼方式)
	 */
	public static void test04(String path) throws IOException{
		Reader reader = new InputStreamReader(new FileInputStream(path),"UTF-8");
		int len = 0;
		char[] cbuf = new char[11];
		while ((len = reader.read(cbuf)) != -1) {
			System.out.print(new String(cbuf,0,len));
		}
	}
	/*
	 * 在test04的基礎上加增強緩沖流,加快讀取速度
	 */
	public static void test05(String path) throws IOException{
		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));
		int len = 0;
		while ((len = reader.read()) != -1) {
			System.out.print((char)len);
		}
	}
	/*
	 * 在test04的基礎上加增強緩沖流,加快讀取速度
	 */
	public static void test05(String path) throws IOException{
		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));
		int len = 0;
		while ((len = reader.read()) != -1) {
			System.out.print((char)len);
		}
	}
}