基礎流的簡單操作
之前學到的File我們隻能操作檔案夾和檔案,卻不能操作裡面的内容。今天通過學習IO流之後,我們就可以操作檔案裡面的内容了。在Java中,處理位元組流的兩個基礎的類是InputStream和OutputStream,而用于處理字元流的兩個基礎的類是Reader和Writer。是以其他的流類都是以這4個類為基礎。首先就說一下InputStream和OutputStream。
FileInoutStream和FileOutputStream分别是InputStream和OutputStream的直接子類,我們可以叫它們為基礎流或者低級流,基本流中構造中參數是媒體。
1. InputStream的方法
read():讀入一個位元組并傳回,包裝為int,傳回-1表示已讀不到
close():關閉資源
首先從讀檔案的内容開始,例如我們先在D盤建立一個檔案a.txt在裡面寫上abcde,那麼我們怎麼把這些内容讀出來呢?看下面的代碼。 |
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; publicclass Test { publicstaticvoid main(String[] args) { InputStream is = null; try {// 輸入流檔案必須存在 is = new FileInputStream("d:\\a.txt"); int i = is.read();//讀第一個位元組 System.out.println(i);//輸出對應的内容,是int類型的如果想輸出原來的内容 //把類型轉換一下就可以了 System.out.println((char)i); //我們把兩個異常合并到一起 } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { }finally{ try {//關閉資源,同樣需要抛出異常 is.close(); } |
執行結果:97 a |
另外的方法:
read(byte[] b) 一次讀入盡可能多的位元組去填滿位元組數組b,傳回實際讀到的位元組數,-1表示已讀不到。
read(byte[] b, int off, int len) 一次讀入盡可能多的位元組去填滿位元組數組b從off開始的len個空間。
如果我們想把abcde全部都讀出來應該怎麼辦呢?這時我們可以借助循環,因為在read()方法中-1表示讀不到了,是以我們可以這麼做
int i = 0; while((i=is.read())!=-1){//如果不是-1代表下面還有位元組 System.out.print((char)i); |
執行結果:abcde |
讀的操作我們已經做到了,接下來就是往檔案裡面寫内容。這時我們就需要使用OutpetStream這個流類。OutputStream類提供的方法:
write():寫一個位元組到流中
write(byte[] b):将位元組數組中的資料寫入流中
write(byte[] b, int off, int len):将位元組數組中從off開始的length個位元組寫入到流中
flush():将緩沖中的位元組立即發送到流中,同時清空緩沖
close():關閉輸出流
寫的操作和讀差別不大,看一下代碼:
import java.io.FileOutputStream; import java.io.OutputStream; OutputStream os = null; try {// 輸出流:自己會建立一個檔案 // true表示追加 false表示覆寫 預設是false os = new FileOutputStream("d:\\b.txt",true); os.write(97);// //下面的這兩個我們隻需要寫一個就行了 //os.flush(); os.close(); |
執行結果根據我們執行的次數而定,因為我們加了true,如果執行一次結果就是a,兩次就是aa,以此類推。 |
如果我們想把a.txt的内容複制到b.txt中應該怎麼做呢?思路就是每當讀一個a.txt中的位元組,就往b.txt裡面寫。代碼也非常簡單。
package day11; import java.io.File; while((i = is.read())!=-1){ char ch = (char)i; os = new FileOutputStream(new File("d:\\b.txt"),true); os.write(ch); |
結果當然就是b.txt裡面也是abcde |
上面我們實作了檔案内容的複制,下面我們來完成壓縮檔案複制的操作,有了上面的代碼我們會有一些思路。在下面的代碼中為了更清晰的展現代碼,我們将抛出異常都交給函數來完成,不再自己處理,但是不建議這樣,現在隻是為了讓代碼清晰,看下面代碼:
publicclass TestCopyFile { publicstaticvoid main(String[] args) throws IOException { //調用下面的方法,左面是以存在的壓縮包,右面是複制生成的壓縮包 copyFile("d:\\day02.rar","d:\\test.rar"); //定義一個方法 publicstaticvoid copyFile(String file1,String file2) throws IOException{ FileInputStream fis = new FileInputStream(new File(file1)); FileOutputStream fos = new FileOutputStream(new File(file2)); int b = 0; // 讀源檔案,将讀入的每個位元組依次寫入目标檔案 while((b=fis.read())!=-1){ fos.write(b); // 流操作的最後一定要關閉 fis.close(); fos.close(); |
執行結果:在D盤有一個test.rar的壓縮包,當然我們可以根據自己電腦來決定複制什麼檔案,如果檔案很大的話,我們可以清楚的看到test.rar的大小會逐漸增大,這是因為我們是按位元組來複制的,很顯然這種複制方法是非常慢的,怎麼提高複制的速度呢?一起看下吧! |
下面是改進的方法,改動的地方不是很大
intb = 0; //定義一個8K的數組 byte[] arrByte = newbyte[8*1024]; // 讀源檔案,将讀入的每個位元組依次寫入目标檔案,按每8K來複制 while((b=fis.read(arrByte))!=-1){ fos.write(arrByte); |
執行結果:如果檔案很大的話,我們可以看到和上面的差別,就是複制速度變快了。 |
但是我們會發現一個問題,那就是複制之後的test.rar變大了一點,這是因為我們是按每8k來複制的,當day02.rar末尾的地方不夠8k時,仍然會按照8k來複制,這樣最後的8k裡面就會自動填入資料,是以變大了,怎樣解決這個問題呢?也很容易,我們隻需要将上面的