IO系統-內存與外設之間數據的交互-抽象回顧

 IO流這個體系中,涉及到了很多設備,有硬盤、控制檯、鍵盤、內存、打印機、掃描儀。。。,如果說,以客戶爲中心,那麼我們的大客戶就是內存了,所有這些輸入輸出設備都是爲了輔助內存而存在的。

總體來說,這些外設分爲3類,文件類、控制檯、鍵盤輸入,如果還要說一個,那就是網卡了,對於網卡暫時不討論。 IO的I指的是Input,那麼Input操作的對象時誰?IO的O指的是Output,那麼Output操作的對象又是誰呢?這兩個都是動詞耶,他們必須要操作一個實體啊,不多想,這個實體就是內存了,具體點說是內存中某一個對象了。Input,就像你往水杯裏面裝水,Output,那就像你把杯子裏面的水倒出來一樣了,那麼裝水倒水這些動作,到底是屬於我們的,還是屬於杯子的呢???

         以前,用到IO流中比較多的就是控制檯和鍵盤了:System.out 和System.in,那麼現在來看看文件操作。需求是:將“D:\\a.java"拷貝到"E:\\b.java",也就是說在E盤下創建一下叫b.java的文件,它具有和a.java一樣的內容,那麼這將是一個怎樣的流程呢?
       1首先,要處理硬盤上面的文件,必須在內存中爲這個文件建立一個File對象,與之映射,我們只用抽象的處理這個File對象,底層就會爲我們具體的操作硬盤了。但是File對象
只能操作自己,無法和其他File對象交互,不可能說一個File對象將自己的內容直接發送給另一個File對象了,這時候流就出現了。
       流程:源文件-源File對象-輸入流對象-內存中轉站-輸出流對象-目的File對象-目的文件,而我們只需要操作輸入流、中轉站和輸出流了,流和中轉站都這麼多,我們又該怎麼選擇呢?
     2然後,就是尋找適合的流對象了和中轉站了。java中的流按照輸入輸出,分爲輸入流和輸出流,這個不用多說了。還有就是字節流和字符流,原本只有字節流的,因爲內存裏面本來就只能存儲0101了,後來爲了能方便操作字符,就在字節流上面進行了包裝。再後來,爲了各種需求和效率問題,又有了緩衝流、字節字符轉換流...等等,就像以前只有泥巴路一樣,後來爲了走車子,有了柏油路,爲了走火車,又有了鐵路,爲了走地鐵,又有了地鐵線路。。。。都是隨着需求不斷改變的。
             上面的源文件a.java是純文本字符的,所以選擇字符輸入流了,即Reader類,爲了提高效率,選擇BufferedReader,
             目的文件b.java 也是純文本的,所以徐那種字符輸出流了,即Writer,爲了提高效率,就選BufferedWriter了。
            中轉站怎麼選呢?我操作文件時,是一行行操作,還是一個個字符,還是一塊塊的?算了,都試一試,看哪個的效率高了。一個個字符操作,用char;一行行的話
用個String;一塊塊的話,就用個char[]了。

   3代碼示例:

    

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

//爲了方便看邏輯,將所有的異常都拋出去了。
public class CopyTextFile {
	public static void main(String[] args) throws IOException{
		long start1=System.currentTimeMillis();
		copy_1();
		long time1=System.currentTimeMillis()-start1;
		System.out.println("一行行的讀,耗時:"+time1);
		
		long start2=System.currentTimeMillis();
		copy_2();
		long time2=System.currentTimeMillis()-start2;
		System.out.println("一塊塊的讀,耗時:"+time2);
		
		long start3=System.currentTimeMillis();
		copy_3();
		long time3=System.currentTimeMillis()-start3;
		System.out.println("一個個字符的讀,耗時:"+time3);

	}

	public static void copy_1() throws IOException {
		
		//1輸入流:BufferedReader
		BufferedReader bufr=new BufferedReader(new FileReader("D:\\a.java"));

		//2輸出流:BufferedWriter
		BufferedWriter bufw=new BufferedWriter(new FileWriter("E:\\b1.java"));
            
		//3:內存中轉站
		//①String:從輸入流中讀取一行暫存String,在將String寫到輸出流,記得換行和刷新
		String line =null;
		while((line=bufr.readLine())!=null)
		{
				bufw.write(line);
				bufw.newLine();
				bufw.flush();
		}

		//關閉流:就像用完水龍頭一樣,要及時的關閉,免得浪費了資源
		bufr.close();
		bufw.close();

	}

	public static void copy_2() throws IOException{
		
		//1輸入流:BufferedReader
		BufferedReader bufr=new BufferedReader(new FileReader("D:\\a.java"));

		//2輸出流:BufferedWriter
		BufferedWriter bufw=new BufferedWriter(new FileWriter("E:\\b2.java"));
            
		//3:內存中轉站
		//②char[]:從輸入流讀一塊數據存到char[],再把這存的數據丟到輸出流
        char[]buf=new char[1024];
		int num=0;
		while((num=bufr.read(buf))!=-1)
		{
              bufw.write(buf,0,num);
		}

		//關閉流:就像用完水龍頭一樣,要及時的關閉,免得浪費了資源
		bufr.close();
		bufw.close();

	}

	public static void copy_3() throws IOException{
		
		//1輸入流:BufferedReader
		BufferedReader bufr=new BufferedReader(new FileReader("D:\\a.java"));

		//2輸出流:BufferedWriter
		BufferedWriter bufw=new BufferedWriter(new FileWriter("E:\\b3.java"));
		
		//3:內存中轉站:
		//③char字符:從輸入流讀一個字符到char,在將char寫入到輸出流,(由於char會被自動提示爲int,所以需要使用int進行轉換)
		 int ch=0;
		 while((ch=bufr.read())!=-1){
			 bufw.write(ch);
		 }

		//關閉流:就像用完水龍頭一樣,要及時的關閉,免得浪費了資源
		bufr.close();
		bufw.close();

	}

}

一行行的讀,耗時:0
一塊塊的讀,耗時:0
一個個字符的讀,耗時:0

              原來使用了Buffer,這幾種方式都在在內存裏面,速度比較快,時間幾乎都是0毫秒了。但是,對於文本文件,建議用一行行的讀,可以有效的提取數據。

         待續。。。。

換個一個500kb的文件測試,隨機一個結果是:

一行行的讀,耗時:64
一塊塊的讀,耗時:7
一個個字符的讀,耗時:20

發現一行行讀最慢,其次一個個讀寫,最快一塊塊。有業務邏輯,需要判斷某行內容,一行行讀吧,需要判斷某一個字符,一個個字符讀吧,如果只是拷貝文件,建議一塊塊的讀,而且不改變文件大小。


發佈了31 篇原創文章 · 獲贊 5 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章