在java中對資料流的操作分為輸入與輸出兩種方式,而且針對此操作提供了一下兩類支援。
- 位元組流(JDK 1.0開始提供):InputStream(輸入位元組流)、OutputStream(輸出位元組流);
- 字元流(JDK 1.1開始提供):Reader(輸入字元流)、Writer(輸出字元流)。
一、位元組流
輸出位元組流 OutputStream
No. | 方法 | 類型 | 描述 |
1 | public void close() throws IOException | 普通 | 關閉位元組流 |
2 | public void flush() throws IOException | 普通 | 強制重新整理 |
3 | public abstract void write(int b) thorws IOException | 普通 | 輸出單個位元組 |
4 | public void write(byte[] b) throws IOException | 普通 | 輸出全部位元組數組資料 |
5 | public void write(byte[] b,int off,int len) throws IOExcption | 普通 | 輸出部分位元組數組資料 |
注:OutputStream類是個抽象類,同時實作了Closeable和Flushable接口,而Closeable繼承了AutoCloseable接口,是以當使用完OutputStream後即使不手動關閉資源,系統也會自動将資源關閉
OutputStream類本身是一個抽象類,如果需要進行檔案操作,可以使用FileOutputStream子類完成。
No. | 方法 | 類型 | 描述 |
1 | public FileOutputStream(File file) throws FileNotFoundException | 構造 | 将内容輸出到指定路徑,如果檔案已存在則使用新的内容覆寫舊的内容 |
2 | public FileOutputStream(File file,boolean append) throws FileNotFoundException | 構造 | 如果将布爾參數設定為true,則表示追加新的内容到檔案中 |
1.使用位元組輸出流将設定好的内容輸出到指定檔案中
package com.tjut.streamTest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class StreamTest01 {
public static void main(String[] args) throws IOException {
//定義要輸出檔案的路徑
File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
//此時由于目錄不存在,是以檔案不能輸出,應該首先建立目錄
if(!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
//利用OutputStream向檔案輸出資訊時如果檔案不存在,則會自動建立(不需要使用者手動調用createNewFile()方法)
OutputStream output = new FileOutputStream(file);
String str = "沒有月色的夜裡,螢火蟲用心點亮漫天的星";
byte[] data = str.getBytes();
output.write(data);
output.close();
}
}
讀者可以嘗試使用單個位元組的方式輸出
for(int i = 0;i < data.length;i++) {
output.write(data[i]);
}
或者輸出部分位元組數組的内容
output.write(data,6,6);
輸入位元組流 InputStream
InputStream的可以對比OutputStream來學習,同樣是抽象類,也不需要手動關閉資源。
No. | 方法 | 類型 | 描述 |
1 | public void close() throws IOException | 普通 | 關閉位元組輸入流 |
2 | public abstract int read() throws IOException | 普通 | 讀取單個位元組 |
3 | public int read(byte[] b) throws IOException | 普通 | 将資料讀取到位元組數組中,同時傳回讀取的資料長度 |
4 | public int read(byte[] b,int off,int len) throws IOException | 普通 | 将資料讀取到部分位元組數組中,同時傳回讀取的資料長度 |
注:read()方法讀到結尾後會傳回-1
InputStream本身是一個抽象類,需要使用FileInputStream類來實作相應的檔案操作
No. | 方法 | 類型 | 描述 |
1 | public FileInputStream(File file) throws FileNotFoundException | 普通 | 設定要讀取檔案資料的路徑 |
2.使用位元組輸入流讀取指定檔案中的資料,并将其輸出到控制台
package com.tjut.streamTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class StreamTest02 {
public static void main(String[] args) throws IOException {
//1.定義要輸入檔案的路徑
File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
if(file.exists()) {//判斷檔案是否存在
//2.使用InputStream進行讀取
InputStream input = new FileInputStream(file);
byte[] data = new byte[1024];//準備一個1024的位元組數組
int len = input.read(data);//3.進行資料讀取,将内容儲存到位元組數組中
input.close();//4.關閉輸入流
System.out.println(new String(data,0,len));
}
}
}
你也可以嘗試使用while循環,每次讀取一個位元組
int foot = 0;
int temp = 0;
while((temp = input.read()) != -1) {
data[foot++] = (byte)temp;
}
二、字元流
字元輸出流Writer
Writer是一個抽象類,實作了Appendable、Closeable(父接口AutoCloseable)和Flushable接口,是以也不需要手動關閉資源。利用Writer類可以實作字元數組(包含了字元串)的輸出
No. | 方法 | 類型 | 描述 |
1 | public void close() throws IOException | 普通 | 關閉字元輸出流 |
2 | public void flush() throws IOException | 普通 | 強制重新整理 |
3 | public Writer append(CharSequence csq) throws IOException | 普通 | 追加資料 |
4 | public void write(String str) throws IOException | 普通 | 輸出字元串資料 |
5 | public void write(char[] cbuf) throws IOException | 普通 | 輸出字元數組資料 |
Writer是一個抽象類,要針對檔案内容進行輸出,可以使用java.io.FileWriter類實作Writer類對象的執行個體化操作。
No. | 方法 | 類型 | 描述 |
1 | public FileWriter(File file) throws IOException | 構造 | 設定輸出檔案 |
2 | public FileWriter(File file,boolean append) throws IOException | 構造 | 設定輸出檔案以及是否進行資料追加 |
3.使用字元輸出流将特定内容寫入指定檔案中
package com.tjut.streamTest;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class StreamTest03 {
public static void main(String[] args) throws IOException {
//1.定義要輸入檔案的路徑
File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
if(!file.getParentFile().exists()) {//判斷目錄是否存在
file.getParentFile().mkdirs();//建立檔案目錄
}
Writer write = new FileWriter(file);//2.執行個體化Writer對象
String str = "美麗的夢和美麗的詩一樣 \r\n" + "都是可遇而不可求的 \r\n" +
"常常在最沒能料到的時刻裡出現";
write.write(str);//3.輸出字元串資料
write.close();//4.關閉輸出流
}
}
字元輸入流Reader
java.io.Reader類是實作字元資料輸入的操作類,在進行資料讀取時可以不使用位元組資料,而直接依靠字元資料(友善進行中文)進行操作。
No. | 方法 | 類型 | 描述 |
1 | public void close() throws IOException | 普通 | 關閉字元輸入流 |
2 | public int read() throws IOException | 普通 | 讀取單個字元 |
3 | public int read(char[] cbuf) throws IOException | 普通 | 讀取字元到字元數組中,傳回讀取長度 |
4 | public long skip(long n) throws IOException | 普通 | 跳過位元組長度 |
注:Reader類實作了Closeable(父接口為AutoCloseable)和Readable接口,是以不需要手動關閉資源
Writer類中存在直接輸出字元串的操作,而Reader類中并沒有直接傳回字元串的操作,這是因為輸出資料時可以采用追加模式,導緻檔案變得非常龐大。如果在Reader類中提供了直接讀取全部資料的方式,就有可能造成記憶體溢出問題。
Reader類是一個抽象類,要實作檔案資料的字元流讀取,可以利用FileReader子類為Reader對象執行個體化。
No. | 方法 | 類型 | 描述 |
1 | public FileReader(File file) throws FileNotFoundException | 構造 | 定義要讀取的檔案路徑 |
4.使用Reader從指定檔案中讀取資料
package com.tjut.streamTest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class StreamTest04 {
public static void main(String[] args) throws IOException {
//1.定義要輸入檔案的路徑
File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
if(file.exists()) {
Reader reader = new FileReader(file);//2.為Reader類對象執行個體化
char[] data = new char[1024];
int len = reader.read(data);//3.進行資料讀取
reader.close();//4.關閉輸入流
System.out.println(new String(data,0,len));
}
}
}
位元組流與字元流的差別
位元組流直接與終端檔案進行資料互動,字元流需要将資料經過緩沖區處理才與終端檔案資料互動。在使用OutputStream輸出資料時即使最後沒有關閉輸出流,内容也可以正常輸出,但是反過來如果使用的是字元輸出流Writer,在執行到最後如果不關閉輸出流,就表示在緩沖區中處理的内容不會被強制性清空,是以就不會輸出資料。如果有特殊情況不能關閉字元輸出流,可以使用flush()方法強制清空緩沖區。
5.強制清空字元流緩沖區
package com.tjut.streamTest;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class StreamTest05 {
public static void main(String[] args) throws IOException {
//1.定義要輸出檔案的路徑
File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
if(!file.getParentFile().exists()) {//判斷目錄是否存在
file.getParentFile().mkdirs();//建立檔案目錄
}
Writer writer = new FileWriter(file);//2.執行個體化Writer類對象
String str = "我喜歡那樣的夢 \r\n" +
"在夢裡 一切都可以重新開始 \r\n" +
"一切都可以慢慢解釋 \r\n" +
"心裡甚至還能感覺到所有被浪費的時光 \r\n" +
"竟然都能重回時的狂喜和感激";
writer.write(str);//3.輸出字元串資料
writer.flush();//強制重新整理緩沖區
}
}
注:在開發中,如果要進行中文時應優先考慮字元流,如果沒有中文問題,建議使用位元組流。
三、轉換流
雖然位元組流和字元流表示兩種不同的資料流操作,但是這兩種流彼此間是可以實作互相轉化的,雖然轉換流的使用情況并不多。
名稱 | InputStreamReader | OutputStreamReader |
定義結構 | public class InputStreamReader extends Reader | public class OutputStreamWriter extends Writer |
構造方法 | public InputStreamReader(InputStream in) | public OutputStreamWriter(OutputStream out) |
6.将位元組輸出流(OutputStream)轉換為字元輸出流(Writer)
package com.tjut.streamTest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class StreamTest06 {
public static void main(String[] args) throws IOException {
//1.定義要輸出檔案的路徑
File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
if(!file.getParentFile().exists()) {//判斷目錄是否存在
file.getParentFile().mkdirs();//建立目錄
}
OutputStream output = new FileOutputStream(file);//位元組流
//将OutputStream類對象傳遞給OutputStreamWriter類的構造方法,而後向上轉型為Writer
Writer writer = new OutputStreamWriter(output);
String str = "胸懷中滿溢著幸福\r\n" +
"隻因為你就在我眼前\r\n" +
"對我微笑 一如當年\r\n" +
"我真喜歡那樣的夢";
writer.write(str);//Writer類的方法
writer.flush();
writer.close();
}
}
檔案操作類的繼承結構如下:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL0cmeNVHbHVmb1cVWxgmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyQzM5EzN1EjM0ETMxgTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
通過繼承結構可以發現,FileWriter與FileReader都是轉換流的子類,也就證明所有要讀取的檔案資料都是位元組資料,所有 的字元都是在記憶體中處理後形成的。