1. 程式人生 > >黑馬程式設計師 總結(十七)——I/O流(一)

黑馬程式設計師 總結(十七)——I/O流(一)

------- android培訓java培訓、期待與您交流! ----------

I/O流

程式在執行時通常要和外部進行互動,從外部讀取資料或向外部裝置傳送資料,這就是所謂的I/O。Java使用抽象概念——流(stream)來描述程式與資料傳送或者接收的通道。I/O流有不同的分類,按照流的方向分為輸入流和輸出流。按照操作的資料分為位元組流和字元流。在I/O流中有四個基本抽象類,位元組流2個,字元流兩個。位元組流的抽象基類是:InputStream和OutputStream兩個。字元流的抽象基類是:Reader和Writer兩個。由這四個類派生出來的子類名稱都是以其父類名作為子類名的後半部分。

字元流——Writer

一、FileWriter

1、簡介:用來寫入字元檔案的便捷類,用於寫入字元流。

2、構造方法:

1、FileWriter(File file):根據給定的 File 物件構造一個 FileWriter 物件。

2、FileWriter(File file, boolean append) :根據給定的 File 物件構造一個 FileWriter 物件,當append為true為真時,則是在給定的File物件後面新增。

3、FileWriter(FileDescriptor fd) :構造與某個檔案描述符相關聯的 FileWriter 物件

4、FileWriter(String fileName)

 :根據給定的檔名構造一個 FileWriter 物件

5、FileWriter(String fileName, boolean append):根據給定的檔名以及指示是否附加寫入資料的 boolean 值來構造 FileWriter 物件。

二、字元流的寫入

1、匯入java.io包。

2、建立一個FileWriter(寫入字元流)物件,該物件只有自己特有的構造方法用於建立物件。在建立該物件時必須指定要操作的檔案。該檔案會被建立到指定目錄下。如果該目錄下已有同名檔案,將被覆蓋。實際上該步就是在明確操作的物件。

3、呼叫public void write()方法,將要寫入的資料寫入到流中。

4、呼叫public void flush()方法,將流中的資料寫入到檔案中。

5、如果是最後一次寫入資料,則可以public void close()方法,將流中的資料刷到目標檔案中,並且在重新整理後關閉該流。

注:在建立寫入字元流物件,操作完成後必須呼叫close方法關閉流物件。

示例:

import java.io.*;
class MyFileWriter 
{
	public static void main(String[] args) throws IOException,InterruptedException
	{
		FileWriter fw = new FileWriter("hello.java");
		//呼叫write方法往hello.java檔案中寫入流中
		fw.write("import java.io.*;");
		//呼叫flush方法將流中的資料寫到hello.java檔案中
		fw.flush();
		//繼續往流中寫入資料
		fw.write("\nclass MyFileWriter");
		//將流中資料寫入檔案中
		fw.close();
		
		//使用Runtime類的方法,開啟建立的檔案,並且在5秒後自動關閉。
		Runtime rt = Runtime.getRuntime();
		Process p = rt.exec("E:\\xp\\Program Files\\EditPlus 3\\EditPlus.exe J:\\JAVA\\day18\\hello.java");
		Thread.sleep(5000);
		p.destroy();
	}
}

三、檔案的續寫,即在原檔案的基礎上繼續寫。

1、方法:利用FileWriter的的FileWriter(String fileName, boolean append)構造方法。此時,不會新建檔案,而是當原始檔存在時在原檔案的基礎上新增。操作方法和字元流的寫入一樣。

2、在記事本中\r\n代表換行。

四、BufferWriter:

1、簡介:字元流寫入緩衝區,將文字寫入字元輸出流,緩衝各個字元,從而提供單個字元、陣列和字串的高效寫入。可以指定緩衝區的大小,或者接受預設的大小。在大多數情況下,預設值就足夠大了。

2、寫入流緩衝區的建立:

1.因為緩衝區的出現是為了提高流的工作效率,所以在建立緩衝區之前,必須要有流物件。所以首先得建立寫入流的物件。

2.把需要提高效率的流物件作為引數傳遞給緩衝區的建構函式即可。

3、工作原理:可以理解為在緩衝區內封裝了陣列。

4、緩衝區的關閉:緩衝區的關閉實際上是關閉與該緩衝區關聯的流物件。

5、緩衝區類的方法和寫入流方法的對比:

緩衝區是為了提高工作效率而出現的,所以緩衝區的方法和寫入流的方法基本相同。只是寫入流有String getEncoding()方法,返回該寫入流使用的字元編碼名稱。在緩衝區類中有有public void newLine()方法,寫入一個換行符。因為不同的作業系統,換行符的表現形式不一樣。為了實現跨平臺性,讓jvm呼叫系統的方法加上該系統的換行符。

五、IO異常的處理

1、IO異常的由來:因為IO的操作在呼叫資源,所以在和裝置上的資料進行操作的都可能會發生異常。

2、如果幾個連續的語句都可能拋IO異常,則把這幾個語句放在一個try語句裡,因為如果上面發生異常,下面的語句也就沒必要繼續執行。

3、定義異常處理的方式的時候,因為關流的操作必須得進行,所以把關流的語句放在finally語句塊中。

4、在兩個語句塊中都要用到流物件,所以流物件在try語句塊的上面建立引用,在裡面建立物件。這樣finally才能使用關閉流的功能。

5、finally中關閉流資源的操作也可能丟擲IO異常,所以在finally語句中要對關閉流操作的語句也要進行try處理。

6、如果在初始化時丟擲IO異常,則流物件沒有建立成功,但是還是要執行finally語句中關閉流的語句。所以在關閉流物件的語句前面應該加一句流物件是否為null的判斷。

示例

import java.io.*;
class MyFileWriter 
{
	public static void main(String[] args)
	{
		FileWriter fw = null;
		try
		{
			fw = new FileWriter("hello.java");
			//呼叫write方法往hello.java檔案中寫入流中
			fw.write("import java.io.*;");
			//呼叫flush方法將流中的資料寫到hello.java檔案中
			fw.flush();
			//繼續往流中寫入資料
			fw.write("\nclass MyFileWriter");
		}
		catch (IOException e)
		{
			System.out.println("deal:"+e);
			return;
		}
		//關閉流資源
		finally
		{
			if(fw!=null)
				try
				{
					fw.close();
				}
				catch (IOException e)
				{
					System.out.println("deal with:"+e);
					return;
				}
		}

		//使用Runtime類的方法,開啟建立的檔案,並且在5秒後自動關閉。
		
		Runtime rt = Runtime.getRuntime();
		Process p = null;
		//處理開啟程序可能丟擲的異常
		try
		{
			p = rt.exec("E:\\xp\\Program Files\\EditPlus 3\\EditPlus.exe J:\\JAVA\\day18\\hello.java");	
		}
		catch (IOException e)
		{
			System.out.println("deal:"+e);
			return;
		}
		//處理延時丟擲的終端異常
		try
		{
			Thread.sleep(5000);
		}
		catch (InterruptedException e)
		{
			System.out.println("時間到");
		}
		p.destroy();
	}
}

字元流——Reader

一、FileReader(與FileWriter相對)

1、簡介:用來讀取字元檔案的便捷類,用於讀取字元流。

2、構造方法:

1、FileReader(File file)  :在給定從中讀取資料的File 的情況下建立一個新FileReader。

2、FileReader(FileDescriptor fd):在給定從中讀取資料的FileDescriptor 的情況下建立一個新FileReader

3、FileReader(String fileName) :在給定從中讀取資料的檔名的情況下建立一個新FileReader

二、文字檔案的讀取

1、通過Reader類中int read()方法,一個字元一個字元的讀取。

步驟:和寫入字元的類似。

示例:

import java.io.*;
class MyFileReader
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("SystemDemo.java");

		for(int num=fr.read();num!=-1;num=fr.read())
		{
			System.out.print((char) num);
		}
		fr.close();
	}
}


2、通過Reader類中int read(char[] arr)方法,一段字元一段字元的讀取。

示例:

import java.io.*;
class MyFileReader
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("SystemDemo.java");
		char[] i = new char[10];

		for(int num=fr.read();num!=-1;num=fr.read())
		{
			System.out.print(new String(i,0,num));
		}
		fr.close();
	}
}
注意:1、在列印的時候不能用ln,如果用ln就可能原檔案沒有換行,在列印到螢幕上的時候卻換行了。

  2、結束的時候一定要關閉流。

檔案讀寫應用的實驗:

·1、需求:把當前目錄下的一個文字檔案,複製到另一個資料夾。

2、原理:在指定目錄新建一個文字檔案並與之關聯輸出流。把當前目錄下的文字檔案與輸入流關聯,把從該檔案讀取的內容寫到指定目錄的檔案中。

3、示例:

import java.io.*;
class  ReadWrite
{
	public static void main(String[] args) throws IOException
	{	
		//建立輸出流和輸入流的流物件
		FileWriter fw = new FileWriter("d:\\SystemDemo.txt",true);
		FileReader fr = new FileReader("SystemDemo.java");
		//把文字檔案的內容取出並寫入另一個檔案
		char[] a = new char[1024];
		int flag = fr.read(a);
		while (flag!=-1)
		{
			fw.write(new String(a,0,flag));
			fw.flush();
			flag = fr.read(a);
		}
		//關閉流資源
		fw.close();
		fr.close();
	}
}

注意:在輸出流向目標檔案寫入資料的時候,必須要呼叫輸入流的flush方法,把流中的資料刷入檔案。

三、BufferReader

1、簡介:和BufferWriter一樣,只是BufferReader是提高讀的效率的緩衝區,BufferWriter是提高寫效率的緩衝區。

2、BufferReader的建立和關閉:和BufferWriter一樣,只是在關閉的時候不會重新整理。

3、BufferReader和FileReader的對比:

BufferReader中定義了String readLine()讀取文字的一行但是該方法返回的不包含終止符。進行了高效讀取,當讀取完後返回的是null.

注意:readLine()方法,返回的只是回車符之前的字串。所以在拷貝檔案時要手動的新增newLine()方法。

裝飾設計模式

     裝飾模式是在不必改變原類檔案和使用繼承的情況下,動態的擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。目的是對該真實的物件進行功能的增強。

1、裝飾類:定義一個類,將要擴充套件的物件傳入,基於已有的功能,並提供加強功能。該類就被稱為裝飾類。

2、實現方法:裝飾類通常會通過構造方法接收被裝飾的物件。並基於被裝飾的物件的功能,提供更強的功能。

3、裝飾和繼承的區別:

1.繼承用來拓展特定物件的功能,裝飾可以通過多型的特性將一類物件的功能拓展。

2.通過裝飾可以避免通過繼承帶來的程式臃腫的問題。

3.通過繼承得到的體系拓展性沒有裝飾得到的體系拓展性好。

4.因為裝飾類是增強已有物件的功能,具備的功能和已有的功能是相同的,只不過提供了更強的功能,所以裝飾類和被裝飾類是屬於同一個體系。