天天看點

J2SE(5)之IO流(字元流、緩沖流、轉換流)1、字元流2、緩沖流3、中文亂碼的原因

1、字元流

字元流隻能用來操作純文字,否則會破壞檔案;

字元流的兩個接口:Reader和Writer,對應的實作類是:FileReader和FileWriter,它們都是屬于節點流。

1.1 字元流讀純文字檔案

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * 純文字讀取
 */
public class Demo01 {
	public static void main(String[] args) {
		//建立源
		File src =new File("E:/xp/test/a.txt");
		//選擇流
		Reader reader =null;
		try {
			reader =new FileReader(src);
			//讀取操作
			char[] flush =new char[1024];
			int len =0;
			while(-1!=(len=reader.read(flush))){
				//字元數組轉成 字元串
				String str =new String(flush,0,len);
				System.out.println(str);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("源檔案不存在");
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("檔案讀取失敗");
		}finally{
			try {
				if (null != reader) {
					reader.close();
				}
			} catch (Exception e2) {
			}
		}
	}
}
           

1.2 字元流寫純文字檔案

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * 寫出檔案
 */
public class Demo02 {
	public static void main(String[] args) {
		//建立源
		File dest =new File("e:/xp/test/char.txt");
		//選擇流
		Writer wr =null;
		try {
			//追加檔案,而不是覆寫檔案
			wr =new FileWriter(dest);
			//寫出
			String msg ="鋤禾日當午\r\n碼農真辛苦\r\n一本小破書\r\n一讀一上午";
			wr.write(msg);
			wr.append("倒薩發了看電視劇 ");
			
			wr.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if (null != wr) {
					wr.close();
				}
			} catch (Exception e2) {
			}
		}
	}
}
           

2、緩沖流

緩沖流也稱之為處理流,用來增強功能、提供性能,包裝了節點流(使用了裝飾者設計模式)。

1、位元組緩沖流:BufferedInputStream和BufferedOutputStream;

2、字元緩沖流:BufferedReader(它有新方法;readLine() )和BufferedWriter(它有新方法:newLine() )。

2.1 位元組緩沖流拷貝檔案

使用方式:new 緩沖流(new 節點流);

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
 * 位元組流檔案拷貝+緩沖流 ,提高性能
 * 緩沖流(節點流)
 */
public class BufferedByteDemo {
	public static void main(String[] args) {
		
	}
	/**
	 * 檔案的拷貝
	 * @param  源檔案路徑
	 * @param  目錄檔案路徑
	 * @throws FileNotFoundException,IOException
	 * @return 
	 */
		public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {
			//1、建立聯系 源(存在且為檔案) +目的地(檔案可以不存在)  
			File src =new File(srcPath);
			File dest =new File(destPath);
			if(! src.isFile()){ //不是檔案或者為null
				System.out.println("隻能拷貝檔案");
				throw new IOException("隻能拷貝檔案");
			}
			//2、選擇流
			InputStream is =new BufferedInputStream(new FileInputStream(src));
			OutputStream os =new BufferedOutputStream( new FileOutputStream(dest));
			//3、檔案拷貝   循環+讀取+寫出
			byte[] flush =new byte[1024];
			int len =0;
			//讀取
			while(-1!=(len=is.read(flush))){
				//寫出
				os.write(flush, 0, len);
			}
			os.flush(); //強制刷出
			
			//關閉流
			os.close();
			is.close();
		}
}
           

2.2 字元緩沖流拷貝檔案

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
 * 字元緩沖流 +新增方法(不能發生多态)
    拷貝的時候可能出現中文亂碼,亂碼的原因:檔案的編碼和我們目前的eclipse使用的編碼方式不同。
 */
public class BufferedCharDemo {
	public static void main(String[] args) {
		//建立源 僅限于 字元的純文字
		File src =new File("E:/xp/test/Demo03.java");
		File dest =new File("e:/xp/test/char.txt");
		//選擇流
		BufferedReader reader =null;	//因為要使用處理流的readLine方法,是以不能多态	
		BufferedWriter wr =null; //因為要使用處理流的newLine方法,是以不能多态	
		try {
			reader =new BufferedReader(new FileReader(src));
			wr =new BufferedWriter(new FileWriter(dest));
			//讀取操作
			/*
			char[] flush =new char[1024];
			int len =0;
			while(-1!=(len=reader.read(flush))){
				wr.write(flush, 0, len);
			}*/
			//新增方法的操作
			String line =null;
			while(null!=(line=reader.readLine())){
				wr.write(line);
			//wr.append("\r\n");
				wr.newLine(); //換行符号
			}
			wr.flush();//強制刷出
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("源檔案不存在");
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("檔案讀取失敗");
		}finally{
			try {
				if (null != wr) {
					wr.close();
				}
			} catch (Exception e2) {
			}
			try {
				if (null != reader) {
					reader.close();
				}
			} catch (Exception e2) {
			}
		}
	}
}
           

3、中文亂碼的原因

編碼:字元——》位元組,這個過程就是編碼,編成程式可以讀懂的

解碼:位元組——》字元,這個過程就是解碼,解成我們能讀懂的。

那麼亂碼的原因是什麼呢?

1、編解碼的字元集不統一會造成中文亂碼,比如:檔案的字元集是gbk,而eclipse的字元集是utf-8,那麼通過流把檔案的内容讀取并列印到控制台,就會出現亂碼。

2、位元組缺少,長度丢失,導緻亂碼,比如:檔案中本來有“中國”兩個漢字,應該是4個位元組,而我們讀取的時候隻讀取了3個位元組,那麼 國 就會出現亂碼。

public class ConverDemo01 {

	/**
	 * @param args
	 * @throws UnsupportedEncodingException 
	 */
	public static void main(String[] args) throws UnsupportedEncodingException {
		String str ="中國";
		byte[] data =str.getBytes();
		//位元組數不完整
		System.out.println(new String(data,0,3));	
	}
	/**
	 * 編碼與解碼字元集必須相同,否則亂碼
	 * @throws UnsupportedEncodingException 
	 */
	public static void test1() throws UnsupportedEncodingException{
		//解碼 byte -->char
		String str ="中國"; //假設eclipse預設字元集是gbk 
		//編碼 char -->byte
		byte[] data =str.getBytes();
		//編碼與解碼字元集同一
		System.out.println(new String(data));
		data =str.getBytes("utf-8"); //設定編碼字元集
		//編解碼字元集不統一出現亂碼
		System.out.println(new String(data));
				
		//編碼
		byte[] data2 = "中國".getBytes("utf-8");
		//解碼
		str=new String(data2,"utf-8");
		System.out.println(str);
	}
}
           

4、轉換流

轉換流的作用:把位元組流轉成字元流;

因為我們在用字元流進行檔案讀取寫出的時候,當字元集不一緻就會出現中文亂碼,是以我們引入轉換流,它可以指定編解碼的字元集。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * 轉換流: 位元組轉為字元
 * 1、輸出流 OutputStreamWriter 編碼
 * 2、輸入流 InputStreamReader  解碼
 * 
 * 確定源不能為亂碼
 */
public class ConverDemo02 {
	public static void main(String[] args) throws IOException {
		//指定解碼字元集
		BufferedReader br =new BufferedReader(
				new InputStreamReader(
					new BufferedInputStream(
							new FileInputStream( 
									new File("E:/xp/test/Demo03.java"))),"UTF-8")
				);
		//寫出檔案 編碼
		BufferedWriter bw =new BufferedWriter(
				new OutputStreamWriter(
					new BufferedOutputStream(	
					new FileOutputStream(new File("E:/xp/test/encode.java")))));				
		String info =null;
		while(null!=(info=br.readLine())){
			//System.out.println(info);
			bw.write(info);
			bw.newLine();
		}
		bw.flush();
		bw.close();
		br.close();
	}
}