1. 程式人生 > >Java IO流 總結

Java IO流 總結

IO流分類:

1. 輸入流(讀)和輸出流(寫)。

2. 因為處理的資料不同,分為位元組流和字元流。

close()和flush()的區別:

  • flush():將緩衝區的資料刷到目的地中後,流可以使用。
  • close():將緩衝區的資料刷到目的地中後,流就關閉了,該方法主要用於結束呼叫的底層資源。這個動作一定做。

流的操作規律

  1. 明確源和目的
    • 資料來源:就是需要讀取,可以使用兩個體系:InputStream、Reader;
    • 資料匯:就是需要寫入,可以使用兩個體系:OutputStream、Writer;
  2. 操作的資料是否是純文字資料?
    • 如果是:資料來源:Reader
      資料匯:Writer
    • 如果不是:資料來源:InputStream
      資料匯:OutputStream
  3. 明確操作的資料裝置
    • 資料來源對應的裝置:硬碟(File),記憶體(陣列),鍵盤(System.in)
    • 資料匯對應的裝置:硬碟(File),記憶體(陣列),控制檯(System.out)。
  4. 需要在基本操作上附加其他功能嗎?
    • 比如緩衝,如果需要就進行裝飾。


位元組流: InputStream OutputStream

適合操作非文字檔案

處理位元組資料的流物件。裝置上的資料無論是圖片或者dvd,文字,它們都以二進位制儲存的。二進位制的最終都是以一個8位為資料單元進行體現,所以計算機中的最小資料單元就是位元組。意味著,位元組流可以處理裝置上的所有資料,所以位元組流一樣可以處理字元資料。

輸入流:

基類:InputStream(抽象)

實現類: FileInputStream

FileInputStream fi = new FileInputStream(file);

讀取:
int i;
while((i=fi.
read())!=-1){ System.out.print((char)i); }

輸出流:

基類:OutputStream(抽象)

實現類: FileOutputStream

FileOutputStream fo = new FileOutputStream("C:/a.txt",false);

字元流讀寫檔案:

private static void method2(String src, String dest) throws IOException {

//1,指定資料來源

FileInputStream in = new FileInputStream(src);

//2,指定目的地

FileOutputStream out = new FileOutputStream(dest);

//3,讀資料

byte[] buffer = new byte[1024];

int len = -1;

while ( (len=in.read(buffer)) != -1) {

//4,寫資料

out.write(buffer, 0, len);

}

//5,關閉流

in.close();

out.close();

}

【注】

  1. 路徑: C:/a.txt -> C:\\a.txt
  2. false: 不覆蓋檔案,true:更新覆蓋原檔案
  3. 原檔案不存在則新建
  4. 路徑可由 File 物件代替


字元流: Reader Writer

適合操作文字檔案

字元每個國家都不一樣,所以涉及到了字元編碼問題,那麼GBK編碼的中文用unicode編碼解析是有問題的,所以需要獲取中文位元組資料的同時+ 指定的編碼表才可以解析正確資料。為了方便於文字的解析,所以將位元組流和編碼表封裝成物件,這個物件就是字元流。只要操作字元資料,優先考慮使用字元流體系。

輸入流:Reader

實現類:FileReader

//自定義緩衝區
import java.io.*;
class FileReaderDemo2 {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("demo.txt"); //建立讀取流物件和指定檔案關聯。
		//因為要使用read(char[])方法,將讀取到字元存入陣列。所以要建立一個字元陣列,一般陣列的長度都是1024的整數倍。
		char[] buf = new char[1024];
		int len = 0;
		while(( len=fr.read(buf)) != -1) {
			System.out.println(new String(buf,0,len));
		}
		fr.close();
	}
}

輸出流:Writer

實現類:FileWriter



緩衝流: Buffer

位元組緩衝流:

BufferedInputStream

BufferedOutputStream

字元緩衝流 高效 讀取檔案

private static void method4(String src, String dest) throws IOException {

//1,指定資料來源

BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));

 //2,指定目的地

BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));

 //3,讀資料

byte[] buffer = new byte[1024];

int len = -1;

while ( (len = in.read(buffer)) != -1) {

//4,寫資料

out.write(buffer, 0, len);

}
 //5,關閉流

in.close();

out.close();

}

字元緩衝流:

BufferedReader(讀)

FileReader fr = new FileReader("bufdemo.txt");
	BufferedReader bufr  = new BufferedReader(fr);
	String line = null;
	while((line=bufr.readLine())!=null){  //readLine方法返回的時候是不帶換行符的。
		System.out.println(line);
	}
	bufr.close();

BufferedWriter(寫)

	FileWriter fw = new FileWriter("bufdemo.txt");
	BufferedWriter bufw = new BufferedWriter(fw);//讓緩衝區和指定流相關聯。
	for(int x=0; x<4; x++){
		bufw.write(x+"abc");
		bufw.newLine(); //寫入一個換行符,這個換行符可以依據平臺的不同寫入不同的換行符。
		bufw.flush();//對緩衝區進行重新整理,可以讓資料到目的地中。
	}
	bufw.close();//關閉緩衝區,其實就是在關閉具體的流。

字元緩衝流讀寫檔案

public class CopyTextFile {

public static void main(String[] args) throws IOException {

//1,指定資料來源, 是資料來源中讀資料,採用輸入流

BufferedReader in = new BufferedReader(new FileReader("file.txt"));

//2,指定目的地,是把資料寫入目的地,採用輸出流

BufferedWriter out = new BufferedWriter(new FileWriter("copyFile.txt"));

//3,讀資料

String line = null;

while ( (line = in.readLine()) != null ) {

out.write(line);//4,寫資料

out.newLine();//寫入換行符號

}

//5,關閉流

out.close();

in.close();

}

}



轉換流: InputStreamReader OutputStreamWriter

轉換流特有功能

  • 轉換流可以將位元組轉成字元,原因在於,將獲取到的位元組通過查編碼表獲取到指定對應字元。

凡是操作裝置上的文字資料,涉及編碼轉換,必須使用轉換流。

轉換流 InputStreamReader

【注意】:在讀取指定的編碼的檔案時,一定要指定編碼格式,否則就會發生解碼錯誤,而發生亂碼現象。

程式碼演示:

public class InputStreamReaderDemo {

public static void main(String[] args) throws IOException {

//演示位元組轉字元流的轉換流

readCN();

}

public static void readCN() throws IOException{

//建立讀取檔案的位元組流物件

InputStream in = new FileInputStream("c:\\cn8.txt");

//建立轉換流物件

//InputStreamReader isr = new InputStreamReader(in);這樣建立物件,會用本地預設碼錶讀取,將會發生錯誤解碼。

InputStreamReader isr = new InputStreamReader(in,"utf-8");

//使用轉換流去讀位元組流中的位元組

int ch = 0;

while((ch = isr.read())!=-1){

System.out.println((char)ch);

}

//關閉流

isr.close();

}

}

轉換流 OutputStreamWriter

【注意】:在寫出指定的編碼的檔案時,一定要指定編碼格式,否則讀取時編碼格式不同可能發生亂碼現象。

將字串按照指定的編碼表轉成位元組,在使用位元組流將這些位元組寫出去。

程式碼演示:

public static void writeCN() throws Exception {

//建立與檔案關聯的位元組輸出流物件

FileOutputStream fos = new FileOutputStream("c:\\cn8.txt");

//建立可以把字元轉成位元組的轉換流物件,並指定編碼

OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");

//呼叫轉換流,把文字寫出去,其實是寫到轉換流的緩衝區中

osw.write("你好");//寫入緩衝區。

osw.close();

}


列印流

PrintWriter

package com.qfedu.bhy.test_printwriter;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 	列印流輸出異常日誌資訊
 * @author bhy
 *
 */
public class MyException extends Exception{
	
	//設定異常資訊
		public String getMessage() {
			
			return "異常資訊--列印異常日誌";
		}
	//定義異常時執行的方法
	public void printException() {
		
		PrintWriter pw = null;
		FileWriter fw = null;
		try {
			fw = new FileWriter("F:/print.txt",true);//true:檔案不覆蓋
			pw = new PrintWriter(fw);
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			
			this.printStackTrace(pw);//this.printStackTrace(PrintWriter s);  寫出當前異常資訊到指定列印流中
			pw.print(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
					.format(new Date())+"\r\n");//追加時間資訊到列印流中
			//關閉流
			if(fw!=null) {
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(pw!=null) {
				pw.close();
			}
		}
	}

}

附上自定義異常使用程式碼

package com.qfedu.bhy.test_printwriter;

public class TestPrintWriter {

	public static void main(String[] args){
		
		try {   /捕獲異常
			print();
		} catch (MyException e) {   //處理異常
			e.printException();//呼叫自定義異常的異常處理方法
		}
	}
	public static int print()throws MyException{//宣告異常
		
		int[] arr = new int[] {1,4,0,3};
		int n = 0 ;

		for (int i = 0; i < arr.length+1; i++) {
			if(i > arr.length-1 || arr[i] == 0) {
				throw new MyException();//丟擲自定義異常物件
			}else {
				n = arr[i+1]/arr[i];
			}	
		}
		return n;
	}

}


物件流

  • ObjectInputStream
  • ObjectOutputStream

物件流–實現序列化:

import java.io.*;
class ObjectStreamDemo {
	public static void main(String[] args) throws Exception{
		writeObj();
		readObj();
	}
	public static void readObj()throws Exception{
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
		Object obj = ois.readObject();//讀取一個物件。
		System.out.println(obj.toString());
	}
	public static void writeObj()throws IOException{
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
		oos.writeObject(new Person("lisi",25)); //寫入一個物件。
		oos.close();
	}
}
class Person implements Serializable{
	private static final long serialVersionUID = 42L;//生成一個序列化ID號
	private transient String name;//用transient修飾後name將不會進行序列化
	public int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String toString(){
		return name+"::"+age;
	}
}