爲跳槽面試作準備,今天開始進入 Java 基礎的複習。但願基礎很差的同窗看完這篇文章,能掌握泛型,而基礎好的同窗權當複習,但願看完這篇文章可以起一點你的青澀記憶。前端
想象一個場景:咱們在電腦上編輯文件,能夠保存到硬盤上,也能夠拷貝到 U 盤中。那這個看似簡單的過程,背後實際上是數據的傳輸。java
數據的傳輸,也就是數據的流動。既然是流動也就會有方向,有入方向和出方向。舉個上傳文件的栗子,如今有三個對象,文件、應用程序、上傳的目標地址(服務器)。簡化的上傳文件有兩步:python
注意這個入和出是相對的,它相對於應用程序而言。若是相對於服務器而言,這個上傳文件操做就是入方向,從應用程序讀入。Java中I/O操做主要是指使用java.io
包下的內容,進行輸入、輸出操做。輸入也叫作讀取數據,輸出也叫作做寫出數據。linux
我不認同網絡上不少 IO 流的圖,他們只是簡單的把 io 流分紅字節流和字符流。這樣的分類也不是說很差,只是太臃腫、難記。c++
先上一張我本身總結的 IO 留的思惟導圖,我先把它分紅了節點流和處理流,節點流是直接接觸數據源的,而處理流是出於各類目的在節點流的基礎上再套一層的 IO 流。再按照操做類型,分紅 8 個小類,而後纔是字節、字符分類,最後纔是輸入、輸出的分類。具體能夠看如下思惟導圖(可能不清晰,有須要的在後臺回覆IO流獲取原思惟導圖)git
根據數據的流向分爲:輸入流和輸出流。github
其餘設備
上讀取到內存
中的流。內存
中寫出到其餘設備
上的流。根據數據的類型分爲:字節流和字符流。面試
IO 流要說明白鬚要好幾篇才行,今天咱們先複習文件流。算法
全部的文件(包括圖片、音樂、視頻),都是字節。因此字節流能夠傳輸任意文件數據。在操做流的時時,不管使用什麼樣的流對象,底層傳輸的始終爲二進制數據。小程序
文件流也就是直接操做文件的流,文件流又分爲字節流 (FileInputStream
和 FileOutputStream
)和字符流(FileReader
和 FileWriter
)。其中字節流可用於操做一切文件,而字符流只能用於操做文本文件。
java.io.FileOutputStream
類繼承於 OutputStream
是文件輸出流,用於將數據寫出到文件。
構造方法:可用文件路徑構造,也可建立 File 對象以後構造。
寫出數據示例:
/** * Project Name:review_java <br/> * Package Name:com.nasus.io.filestream <br/> * Date:2020/1/5 19:24 <br/> * * @author <a href="turodog@foxmail.com">chenzy</a><br/> */
public class FOSWriterStream {
public static void main(String[] args) throws IOException {
// 使用文件名稱建立流對象,構造函數中的 true 表示在原有數據末尾追加續寫
FileOutputStream fos = new FileOutputStream("fos.txt", true);
// 一、逐個字節寫出
fos.write(97); // 97 的 ascll 碼是 a
fos.write(98); // 98 的 ascll 碼是 b
fos.write(99); // 99 的 ascll 碼是 c
// 二、寫出一個換行, 換行符號轉成數組寫出
fos.write("\r\n".getBytes());
// 字符串轉換爲字節數組
byte[] b = "一個優秀的廢人".getBytes();
// 三、寫出字節數組數據
fos.write(b);
// 四、寫出指定長度字節數組數據(不可超過 b 的長度,不然數組越界)
fos.write(b, 0, b.length);
// 關閉資源
fos.close();
}
}
複製代碼
java.io.FileInputStream
類繼承於 InputStream
是文件輸入流,用於將數據從文件讀出。
構造方法:可用文件路徑構造,也可建立 File 對象以後構造。
讀取數據示例:
/** * Project Name:review_java <br/> * Package Name:com.nasus.io.filestream <br/> * Date:2020/1/5 19:31 <br/> * * @author <a href="turodog@foxmail.com">chenzy</a><br/> */
public class FISReadStream {
public static void main(String[] args) throws IOException {
// 一、逐個讀取字節
int b;
FileInputStream fis1 = new FileInputStream("fis.txt");
// 循環讀取
while ((b = fis1.read())!=-1) {
System.out.println((char)b);
}
// 關閉資源
fis1.close();
System.out.println("----華麗麗的分割線----");
// 二、定義字節數組讀取
int length;
FileInputStream fis2 = new FileInputStream("fis.txt");
// 定義字節數組,做爲裝字節數據的容器
byte[] bytes = new byte[1024];
// 循環讀取
while ((length = fis2.read(bytes))!=-1) {
// 每次讀取後,把數組變成字符串打印
System.out.println(new String(bytes, 0, length));
}
// 關閉資源
fis2.close();
}
}
複製代碼
複製文件示例:
/** * Project Name:review_java <br/> * Package Name:com.nasus.io.filestream <br/> * Date:2020/1/5 19:43 <br/> * * @author <a href="turodog@foxmail.com">chenzy</a><br/> */
public class FileCopyStream {
public static void main(String[] args) throws IOException {
// 指定數據源
FileInputStream fis = new FileInputStream("Java IO 流.png");
// 指定目的地
FileOutputStream fos = new FileOutputStream("流.png");
// 定義數組
byte[] b = new byte[1024];
// 定義長度
int len;
// 循環讀取
while ((len = fis.read(b))!=-1) {
// 寫出數據
fos.write(b, 0 , len);
}
// 關閉資源,後開先關,後開先關
fos.close();
fis.close();
}
}
複製代碼
首先明確一點:一個英文字母佔一個字節,一個漢字佔兩個字節,因此當字節流讀取字符流就會出現亂碼或者顯示不全。因此用字節流操做含有中文字符的文件時,要轉換成字符流並指定編碼格式才能防止亂碼。(這點,後面轉換流會複習到)
當使用字節流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,那是由於一箇中文字符可能佔用多個字節存儲。因此 Java 提供一些字符流類,以字符爲單位讀寫數據,專門用於處理文本文件。
java.io.FileReader
類繼承於 Reader 類,是讀取字符文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。
構造方法:可用文件路徑構造,也可建立 File 對象以後構造。
PS:有時候出現亂碼,多考慮下是否是編碼的緣由:字節與字符的規則對不上。
讀取數據示例:
/** * Project Name:review_java <br/> * Package Name:com.nasus.io.filereadwrite <br/> * Date:2020/1/5 20:19 <br/> * * @author <a href="turodog@foxmail.com">chenzy</a><br/> */
public class FileRead {
public static void main(String[] args) throws IOException {
// 一、逐個字符讀取
int b = 0;
FileReader fileReader1 = new FileReader("read.txt");
// 循環讀取
while ((b = fileReader1.read())!=-1) {
// 自動提高類型提高爲 int 類型,因此用 char 強轉
System.out.println((char)b);
}
// 關閉流
fileReader1.close();
System.out.println("----華麗麗的分割線----");
// 二、利用字符數組,每次讀取兩個字符
int length = 0;
FileReader fileReader2 = new FileReader("read.txt");
char[] charArray = new char[2];
// 讀取數據
while ((length = fileReader2.read(charArray)) != -1) {
System.out.println(new String(charArray, 0, length));
}
// 關閉流
fileReader2.close();
}
}
複製代碼
java.io.FileWriter
類是寫出字符到文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。
構造方法:可用文件路徑構造,也可建立 File 對象以後構造。
寫出數據示例:
public static void main(String[] args) throws IOException {
// 使用文件名稱建立流對象,true 表示在原有數據末尾追加續寫
FileWriter fileWriter = new FileWriter("fw.txt", true);
// 一、逐個寫出字符
fileWriter.write(97);
fileWriter.write('C');
fileWriter.write('Z');
fileWriter.write('Y');
// 中文編碼表中30000對應一個漢字。
fileWriter.write(30000);
// 二、寫出字符串
fileWriter.write("是一個");
// 三、寫出 Windows 換行
fileWriter.write("\r\n");
// 四、寫出字符串數組
// 字符串轉換爲字節數組
char[] chars = "優秀的廢人".toCharArray();
fileWriter.write(chars, 0, chars.length);
// 關閉資源,close方法調用以前,數據只是保存到了緩衝區,並未寫出到文件中。
fileWriter.close();
}
複製代碼
刷新與關閉:
由於內置緩衝區的緣由,若是不關閉輸出流,沒法寫出字符到文件中。可是關閉的流對象,是沒法繼續寫出數據的。若是咱們既想寫出數據,又想繼續使用流,就須要flush
方法了。
flush
:刷新緩衝區,流對象能夠繼續使用。close
:先刷新緩衝區,而後通知系統釋放資源。流對象不能夠再被使用了。/** * Project Name:review_java <br/> * Package Name:com.nasus.io.filereadwrite <br/> * Date:2020/1/5 22:25 <br/> * * @author <a href="turodog@foxmail.com">chenzy</a><br/> */
public class FileFlushClose {
public static void main(String[] args) throws IOException {
// 使用文件名稱建立流對象
FileWriter fw = new FileWriter("fw.txt");
// 一、經過 flush 寫出數據
// 寫出第 1 個字符
fw.write('刷');
fw.flush();
// 繼續寫出第 2 個字符,寫出成功
fw.write('新');
fw.flush();
// 二、經過 close 寫出數據,流關閉後不可用
// 寫出第 1 個字符
fw.write('關');
fw.close();
// 繼續寫出第 2 個字符,【報錯】java.io.IOException: Stream closed
fw.write('閉');
fw.close();
}
}
複製代碼
若是看到這裏,喜歡這篇文章的話,幫忙 " 轉發 "或者點個" 在看 ",行嗎?祝大家 2020 暴富。微信搜索「一個優秀的廢人」,歡迎關注。
回覆「1024」送你一套完整的 java、python、c++、go、前端、linux、算法、大數據、人工智能、小程序以及英語教程。
回覆「電子書」送你 50+ 本 java 電子書。