字符輸出流
昨天我們學習了字符輸入流的學習,而字符流中還剩下字符輸出流等待著我們進行解鎖。
所以今天我們準備對字符輸出流進行一個詳細的了解吧!
字符輸出流的父類(Writer)
Writer是所有的輸出字符流的父類,它是一個抽象類。主要作用是可以將指定的字符信息寫出到目的地。它定義了字符輸出流的基本共性功能方法。
體系結(jié)構

-
OutputStreamWriter是一個連接字節(jié)流和字符流的橋梁。 -
FilterWriter是所有自定義具體裝飾流的父類。 -
BufferedWriter字符緩沖流,通過緩沖區(qū)讀寫,減少系統(tǒng)IO次數(shù),從而提高讀寫的效率。 -
FileWriter是寫出字符到文件的便利類。構造時使用系統(tǒng)默認的字符編碼和默認字節(jié)緩沖區(qū)。
Writer中的方法

與字節(jié)輸入流的用法完全類似,輸入流后續(xù)繼承的子類都有這些方法,需要writer()方法進行讀取文件,使用close()方法關閉資源。
FileWriter
1. 構造方法
-
public FileWriter(File file):創(chuàng)建一個新的FileWriter,給定要讀取的File對象。 -
public FileWriter(File file, boolean append):創(chuàng)建一個新的FileWriter,可以追加數(shù)據(jù)。 -
public FileWriter(String fileName): 創(chuàng)建一個新的FileWriter,給定要讀取的文件的名稱。 -
public FileWriter(String fileName, boolean append):創(chuàng)建一個新的FileWriter,可以追加數(shù)據(jù)。
演示如下:
public class WriterTest {
public static void main(String[] args) throws IOException {
//public FileWriter(File file)
// 使用File對象創(chuàng)建流對象
File file = new File("e:\\demo\\bjx.txt");
FileWriter fw = new FileWriter(file);
//public FileWriter(String fileName)
// 使用文件名稱創(chuàng)建流對象
FileWriter fw2 = new FileWriter("e:\\demo\\bjx.txt");
}
}
復制代碼
可以發(fā)現(xiàn),程序運行后,在文件中自動幫我們生成了bjx.txt文件。跟字節(jié)輸出流一樣。
追加數(shù)據(jù)的構造方法就不帶大家演示了,上面也有專門演示過了。嘿嘿,不要說我懶,因為我相信你學了上面的字節(jié)輸出流的,這里你肯定懂了,對吧。大家都這么聰明,學習Java的天才,一點就懂的啦。
2. 寫出數(shù)據(jù)
既然能創(chuàng)建出來FileWriter對象了,那我們就具體實踐下寫出數(shù)據(jù)吧。
-
public void write(int c):每次可以寫出一個字符數(shù)據(jù)。public class WriterTest2 { public static void main(String[] args) throws IOException { // 使用文件名稱創(chuàng)建流對象 FileWriter fw = new FileWriter("e:\\demo\\bjx.txt"); // 寫出數(shù)據(jù) fw.write(97);//存入到文件中應為:a fw.write(26666);//存入到文件中應為:株 /* 【特別注意】與字節(jié)輸出流FileOutputStream不同的是。 如果不關閉資源,數(shù)據(jù)只是保存到緩沖區(qū),并未保存到文件。 */ //fw.close(); } } 復制代碼程序運行后,可以看到如果我沒有注釋掉
fw.close()即有關閉資源的情況下,是可以保存到文件中,但是呢,如果沒有關閉資源,它則沒有保存到文件。這是為什么呢?一個字符 = 兩個字節(jié),而文本中數(shù)據(jù)存儲的基本單位是字節(jié)。是不是字節(jié)輸出流就可以直接寫進去呢,而字符流,是沒辦法直接存儲進去。
-
而字符流是通過緩沖區(qū)的方式進行存儲的,如果沒有使用方法是無法將緩沖區(qū)的內(nèi)容保存到文件中的。
可以通過
write()方法一步一步點進去看源碼,可以發(fā)現(xiàn)他存進去了一個CharBuffer緩沖區(qū)中。image.png
* 因為內(nèi)置緩沖區(qū)的原因,如果不關閉輸出流,無法寫出字符到文件中。而如果一旦關閉流資源后,我們就沒辦法再寫入數(shù)據(jù),所以如果我我們既想寫出數(shù)據(jù),又想繼續(xù)使用流,就需要`flush()` 方法了。
看源碼可以發(fā)現(xiàn),`flush()` 方法和`close()` 方法最終都會調(diào)用`StreamEncoder`中的`writeBytes()`。

`flush()` :刷新緩沖區(qū),流對象可以繼續(xù)使用。 `close()` :先刷新緩沖區(qū),然后通知系統(tǒng)釋放資源,流對象不可以再被使用了。
最終可以改進為:
```
public class WriterTest3 {
public static void main(String[] args) throws IOException {
// 使用文件名稱創(chuàng)建流對象
FileWriter fw = new FileWriter("e:\\demo\\bjx.txt");
// 寫出數(shù)據(jù)
//public void write(String str)
fw.write("北極星");
//fw.write('叫我');//字符不能多寫,而字符串可以
fw.flush();
fw.write("叫我");
fw.flush();//一般每寫入一個就刷新下緩沖區(qū)。
// 如果你在最后寫,如果這過程中出現(xiàn)異常等錯誤,是不是寫入了呢?
fw.write("視頻聊天啦");
fw.flush();
fw.close();//就算我注釋掉,也是有加入數(shù)據(jù)了的
//fw.write("能成功嗎"); // 當我們要執(zhí)行這里后,就會【報錯】java.io.IOException: Stream closed
//fw.close();
}
}
復制代碼
```
可以發(fā)現(xiàn):
* 我們可以通過`flush()`方法實現(xiàn)寫入數(shù)據(jù)到文件中。
* 即便是`flush()`方法寫出了數(shù)據(jù),操作的最后還是要調(diào)用`close()` 方法,釋放系統(tǒng)資源。
-
puiblic write(char[] cbuf)和public write(char[] cbuf, int off, int len):每次可以寫出字符數(shù)組中的數(shù)據(jù)。這兩個功能用法和字節(jié)輸出流類似,直接演示看下吧:public class WriterTest4 { public static void main(String[] args) throws IOException { // 使用文件名稱創(chuàng)建流對象 FileWriter fw = new FileWriter("e:\\demo\\bjx.txt"); // 字符串轉(zhuǎn)換為字節(jié)數(shù)組 char[] chars = "北極星".toCharArray(); // 寫出字符數(shù)組 //puiblic write(char[] cbuf) fw.write(chars); // 北極星 fw.flush(); //寫出從索引0開始,2個字節(jié) //public write(char[] cbuf, int off, int len) fw.write(chars,0,2);//北極 fw.flush(); fw.close(); } } 程序執(zhí)行后,bjx.txt的文件信息為: 北極星北極 復制代碼
3. 實現(xiàn)換行
既然在字節(jié)輸出流中,我們可以實現(xiàn)換行的功能,那我們字符流可以嗎?答案當然可以的啦,跟字節(jié)輸出流一樣的操作。來看看吧:
public class WriterTest5 {
public static void main(String[] args) throws IOException {
// 使用文件名稱創(chuàng)建流對象
FileWriter fw = new FileWriter("e:\\demo\\bjx.txt");
fw.write("北極星叫");
fw.flush();
// 寫出換行
fw.write("\r\n");
fw.flush();
fw.write("我一起看流星雨");
fw.flush();
fw.close();
}
}
程序執(zhí)行后,bjx.txt的文件信息為:
北極星叫
我一起看流星雨
復制代碼
復制文本案例
復制的原理已經(jīng)在字節(jié)流的時候講解過了。現(xiàn)在直接上代碼給各位看官瞧瞧如何:
public class CopyTxtTest {
public static void main(String[] args) throws IOException {
// 1\. 創(chuàng)建輸入和輸出流對象。
// 1.1 指定要讀文件的路徑。
FileReader fr = new FileReader("E:\\demo\\青春.txt");
// 1.2 指定目的地文件的路徑。
FileWriter fw = new FileWriter("E:\\demoCopy\\青春.txt");
// 2.讀寫數(shù)據(jù)
// 2.1 定義字符數(shù)組
char[] chs = new char[1024];
int len;
// 2.2 循環(huán)讀取出數(shù)據(jù)
while ((len = fr.read(chs)) != -1) {
// 2.3 將得到的字節(jié)數(shù)據(jù)寫出
fw.write(chs, 0, len);
fw.flush();
}
// 3.關閉所有資源
fw.close();
fr.close();
}
}
復制代碼
程序執(zhí)行后,看下文件的信息:

小結(jié)
字符流,只能操作文本文件,不能操作圖片,視頻等非文本文件。當我們單純讀或者寫文本文件時可以使用字符流更高效的操作文本文件,而其他情況使用字節(jié)流。
-
兩者的區(qū)別:
- 讀寫單位不同:字節(jié)流以字節(jié)(8bit)為單位,字符流以字符為單位,根據(jù)碼表映射字符,一次可能讀多個字節(jié)。
- 處理對象不同:字節(jié)流能處理所有類型的數(shù)據(jù)(如圖片、avi等),而字符流只能處理字符類型的數(shù)據(jù)。
總結(jié)
相信各位看官都對IO流中字符輸出流類有了一定了解,期待等待下一章的IO高級流教學吧!
當然還有很多流等著下次一起看吧!歡迎期待下一章的到來!
學到這里,今天的世界打烊了,晚安!雖然這篇文章完結(jié)了,但是我還在,永不完結(jié)。我會努力保持寫文章。來日方長,何懼車遙馬慢!
感謝各位看到這里!愿你韶華不負,青春無悔!
作者:太子爺哪吒
鏈接:https://juejin.cn/post/6994321703216087070
來源:掘金
