一、流類
Java的流式輸入/輸出是建立在四個抽象類的基礎上的:InputStream、OutputStream、Reader、Writer。它們用來創建具體的流式子類。盡管程序通過具體子類執行輸入/輸出操作,但頂層類定義了所有流類的基本通用功能。
InputStream和OutputStream為字節流設計,Reader和Writer為字符流設計,字節流和字符流形成分離的層次結構。一般來說,處理字符或字符串使用字符流類,處理字節或二進制對象使用字節流。
操作文件流時,不管是字符流還是字節流,都可以按照以下方式進行:
1、使用File類找到一個對象
2、通過File類的對象去實例化字節流或字符流的子類
3、進行字節(字符)的讀、寫操作
4、關閉文件流
二、OutputStream(字節輸出流)
OutputStream是定義了Java流式字節輸入模式的抽象類。該類的所有方法返回一個void值並且在出錯的情況下引發一個IOException,OutputStream提供的抽象方法有:
方 法 | 作 用 |
void close() | 關閉輸入流,關閉后的寫操作會引發IOException |
flush() | 刷新此輸入流並強制寫出所有緩沖的輸出字節 |
write(byte[] b) | 向輸入流寫入單個字節,注意參數是一個int型,它允許設計者不必把參數轉換成字節型就可以調用write()方法 |
write(byte[] b, int off, int len) | 以b[off]為起點,向文件寫入字節數組b中len個字節 |
write(int b) | 向一個輸出流寫一個完整的字節數組 |
三、FileOutputStream(文件字節輸出流)
FileOutpuStream應該是Java中最常見的字節輸出流了,它創建一個可向文件寫入字節的類OutputStream,它常用的構造方法如下:
1、FileOutputStream(String name)
2、FileOutputStream(File file)
3、FileOutputStream(File file, boolean append)
前兩個構造方法類似,前者輸入文件的絕對路徑,后者輸入File的實例對象,和RandomAccessFile一樣,推薦后者。第三個構造方法有一點不同,append如果設置為true,文件則以搜索路徑模式打開。FileOutputStream的創建不依賴於文件是否存在,在創建對象時,FileOutputSStream會在打開輸出文件之前就創建它。這種情況下如果試圖打開一個只讀文件,會引發IOException。FileOutputStream,寫一個例子,現在我的D盤下的Files文件夾里並沒有"stream.txt"這個文件:
package com.demo; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class FileOutputStreamTest { public static void main(String[] args) throws Exception{ File file = new File("D:/Files/stream.txt"); OutputStream out = new FileOutputStream(file); byte b[] = "Hello World!!!".getBytes(); //操作字節流,要轉換成字節 out.write(b); out.close(); } }
此時打開"stream.txt":
到D盤下的Files文件夾里多了"stream.txt",且文件中的內容和我們寫入的一致,同樣這個例子也證明了FileOutputStream並不依賴指定路徑下的文件是否存在。那如果指定路徑下本來就有文件,那么寫將會覆蓋而不是追加,很好證明:
package com.demo; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class FileOutputStreamTest { public static void main(String[] args) throws Exception{ File file = new File("D:/Files/stream.txt"); OutputStream out = new FileOutputStream(file); byte b[] = "abcdefghijklmnopqrstuvwxyz".getBytes(); //操作字節流,要轉換成字節 out.write(b); out.close(); } }
此時再打開"stream.txt":
"stream.txt"中的內容變掉了,證明了結論。
四、InputStream(字節輸入流)
InputStream是定義了Java流式字節輸入模式的抽象類。該類所有方法在出錯的時候都會引發一個IOException,InputStream提供的抽象方法有:
方 法 | 作 用 |
int available() | 返回當前可讀的字節數 |
void close() | 關閉此輸入流並釋放與該流關聯的所有系統資源,關閉之后再讀取會產生IOException |
int mark(int readlimit) | 在輸入流中放置一個標記,該流在讀取N個Bytes字節前都保持有效 |
boolean markSupported() | 如果調用的流支持mark()/reset()就返回true |
int read() | 如果下一個字節可讀取則返回一個整形,遇到文件尾時返回-1 |
int read(byte b[]) | 試圖讀取buffer.length個字節到buffer中,並返回實際成功讀取的字節數,遇到文件尾則返回-1 |
int read(byte b[], int off, int len) | 將輸入流中最多len個數組直接讀入byte數組,off表示數組b中寫入數據的初始偏移量。注意,三個read方法,在輸入數據可用、檢測到流末尾或者拋出異常前,此方法將一直阻塞 |
void reset() | 重新設置輸入指針到先前設置的標記處 |
long skip(long n) | 跳過和丟棄此輸入流中數據的n個字節 |
五、FileInputStream(文件字節輸入流)
FileInputStream應該是Java中最常見的字節輸入流了,它創建一個能從文件讀取字節的InputStream類,它的兩個常用構造方法如下:
1、FileInputStream(String name)
2、FileInputStream(File file)
和FileOutputStream差不多,推薦后者的用法。FileInputStream,同樣寫一個例子,操作的是上面D盤下的Files文件夾生成的"stream.txt":
package com.demo; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class FileInputStreamTest { public static void main(String[] args) throws Exception{ File file = new File("D:/Files/stream.txt"); InputStream in = new FileInputStream(file); byte b1[] = new byte[(int)file.length()]; int i = 0; i = in.read(b1); System.out.println(i); System.out.println(new String(b1, 0, i)); } }
運行結果為:
26
abcdefghijklmnopqrstuvwxyz
要區分清楚,OutputStream的作用是將內容由Java內存輸出到文件中、InputStream是將內容由文件輸入到Java內存中。read(byte b[])方法之前講明了,表示"試圖讀取buffer.length個字節到buffer中,並返回實際讀取的字節數",返回的是實際字節的大小。