Java的IO流都是由四個抽象基類派生的:
- InputStream、OutputStream:字節流,傳輸二進制文件,比如音頻、視頻、圖片等。
- Reader、Writer:字符流,傳輸文本文件。
在計算機中,所有的文件都能以二進制(字節)形式存在,Java的IO中針對字節傳輸操作提供了一系列的流,統稱爲字節流。字節流有兩個抽象基類InputStream和OutputStream,分別處理字節流的輸入輸出,所有的字節輸入流都繼承自InputStream類,所有的字節輸出流都繼承自OuyputStream類。
在Java中,提供了一系列用於操作文件讀寫的有關方法,接下來先了解一下InputStream類的方法:
- int available():返回此輸入流下一個方法調用可以不受阻塞的從此輸入流讀取的估計字節流。
- void close():關閉此輸入流並釋放與該流關聯的所有系統資源。
- void mark(int readlimit):在此輸入流中標記當前的位置。
- boolean markSupported():測試粗輸入流是否支持mark和reset方法。
- long skip(long n):跳過和丟棄此輸入流中數據的n個字節。
- int read():從輸入流中讀取數據的下一個字節。
- int read(byte[] b):從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組b中,返回讀取的字節流。
- int read(byte[] b,int off,int len):將輸入流中最多len個數據字節讀入byte數組。
- void reset():將此流重新定位到最後一次對此輸入流調用mark方法時的位置。
下面我再來介紹一下OutputStream類的相關方法:
- void close():關閉此輸出流並釋放與此流有關的所有系統資源。
- void flush():刷新此輸出流並強制寫出所有緩衝的輸出字節。
- void write(byte[] b):將b.length個字節從指定的byte數組寫入此輸出流。
- void write(int b):將指定的字節寫入此輸入流。
- void write(byte[] b,int off,int len):將指定byte數組中從偏移量off開始的len個字節寫入此輸出流。
字節流讀寫文件
首先在當前目錄新建一個文本文件read.txt,文件內容爲Hello World!!!
創建文件完成後,開始編寫代碼:
import java.io.FileInputStream;
public class TestFileInputStream {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileInputStream fis=null;
try {
//創建文件輸入流對象
fis=new FileInputStream("read.txt");
int n=512; //設定讀取的字節數
byte buffer[]=new byte[n];
//讀取輸入流
while((fis.read(buffer,0,n)!=-1)&&(n>0)){
System.out.print(new String(buffer));
}
}catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}finally {
try {
fis.close();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
運行結果:
與FileInputStream對應的是FileOutputStream,它是用來將數據寫入文件,操作文件字節輸出流的,接下來通過一個案例來演示如何將數據寫入文件。
import java.io.*;
public class TestFileOutputStream {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("輸入要保存文件的內容:");
int count,n=512;
byte buffer[]=new byte[n];
count=System.in.read(buffer); //讀取標準輸入流
//創建文件輸出流對象
FileOutputStream fos=new FileOutputStream("read.txt");
fos.write(buffer,0,count); //寫入輸出流
System.out.println("已保存到read.txt文件!");
fos.close(); //釋放資源
}
}
運行結果:
在實際開發中,往往讀和寫都是結合使用的,比如文件的複製。
接下來通過一個案例來演示輸入輸出流實現文件的複製。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileCopy {
public static void main(String[] args) throws IOException{
//創建文件輸入流對象
FileInputStream fis=new FileInputStream("src\\lina.jpg");
//創建文件輸出流對象
FileOutputStream fos=new FileOutputStream("tar\\lina_new.jpg");
int len; //定義len,記錄每次讀取的字節數
//複製文件前的系統時間
long begin=System.currentTimeMillis();
//讀取文件並判斷是否到達文件末尾
while((len=fis.read())!=-1) {
fos.write(len); //將獨到的字節寫入文件
}
long end=System.currentTimeMillis();
System.out.println("複製文件耗時:"+(end-begin)+"毫秒");
fis.close();
fos.close();
}
}
運行結果:
字節流的緩衝區
上面的方法複製文件,頻繁操作文件,效率非常低,利用字節流的緩衝區可以解決這一問題,提高效率。
接下來通過一個案例來演示如何在複製文件時應用緩衝區提高效率。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileCopyBuffer {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//創建文件輸入流對象
FileInputStream fis=new FileInputStream("src\\lina.jpg");
//創建文件輸出流對象
FileOutputStream fos=new FileOutputStream("tar\\lina_new1.jpg");
byte[] b=new byte[512]; //定義緩衝區大小
int len; //定義len,記錄每次讀取的字節數
//複製文件前的系統時間
long begin=System.currentTimeMillis();
//讀取文件並判斷是否到達文件末尾
while((len=fis.read(b))!=-1) {
fos.write(b,0,len); //將獨到的字節寫入文件
}
long end=System.currentTimeMillis();
System.out.println("複製文件耗時:"+(end-begin)+"毫秒");
fis.close();
fos.close();
}
}
運行結果:
字節緩衝流
在IO中的一些流會用到裝飾設計模式,分別是BufferedInputStream類和BUfferedOutputStream類,他們的構造方法中分別接收InputStream和OutputStream類型的參數作爲被修飾的對象,在執行讀寫操作時提供緩衝功能。
接下來通過一個案例來演示這兩個流的使用。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestBuffered {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//創建文件輸入流對象
FileInputStream fis=new FileInputStream("src\\lina.jpg");
//創建文件輸出流對象
FileOutputStream fos=new FileOutputStream("tar\\lina_new2.jpg");
//將創建的節點流的對象作爲形參傳遞給緩衝流的構造方法中
BufferedInputStream bis=new BufferedInputStream(fis);
BufferedOutputStream bos=new BufferedOutputStream(fos);
int len; //定義len,記錄每次讀取的字節數
//複製文件前的系統時間
long begin=System.currentTimeMillis();
//讀取文件並判斷是否到達文件末尾
while((len=bis.read())!=-1) {
bos.write(len); //將獨到的字節寫入文件
}
long end=System.currentTimeMillis();
System.out.println("複製文件耗時:"+(end-begin)+"毫秒");
bos.close();
bis.close();
}
}
運行結果: