文章目錄
數據的讀寫–IO流
IO概述
當你電腦上插入一個U盤,可以把一個視頻,拷貝到你的電腦硬盤裏。我們把這種數據的傳輸,可以看做是一種數據的流動,按照流動的方向,
以內存爲基準,分爲 輸入input 和 輸出output ,即流向內存是輸入流,流出內存的輸出流。
Java中I/O操作主要是指使用
java.io 包
下的內容,進行輸入、輸出操作。輸入也叫做讀取數據,輸出也叫做作寫出數據。那麼數據都是在哪些設備上的呢?鍵盤、內存、硬盤、外接設備等等。
IO分類
根據數據的流向分爲:輸入流和輸出流。
輸入流 :把數據從 其他設備 上讀取到 內存 中的流。
輸出流 :把數據從 內存 中寫出到 其他設備 上的流。
格局數據的類型分爲:字節流和字符流。
字節流 :以字節爲單位,讀寫數據的流。
字符流 :以字符爲單位,讀寫數據的流。
頂級父類們
輸入流 | 輸出流 | |
---|---|---|
字節流 | 字節輸入流 InputStream | 字節輸出流 OutputStream |
字符流 | 字符輸入流 Reader | 字符輸出流 Writer |
字節流InputStream/OutputStream
一切文件數據(文本、圖片、視頻等)在存儲時,都是以二進制數字的形式保存,都一個一個的字節,那麼傳輸時一樣如此。所以,字節流可以傳輸任意文件數據。在操作流的時候,我們要時刻明確,無論使用什麼樣的流對象,底層傳輸的始終爲二進制數據。
字節輸出流OutputStream
java.io.OutputStream
抽象類是表示字節輸出流的所有類的超類,將指定的字節信息寫出到目的地。它定義了字節輸出流的基本共性功能方法。
public void close()
:關閉此輸出流並釋放與此流相關聯的任何系統資源。當完成流的操作時,必須調用此方法,釋放系統資源。public void flush()
:刷新此輸出流並強制任何緩衝的輸出字節被寫出。public void write(byte[] b)
:將b.length
字節從指定的字節數組寫入此輸出流。public void write(byte[] b, int off, int len)
:從指定的字節數組寫入len
字節,從偏移量off
開始輸出到此輸出流。public abstract void write(int b)
:將指定的字節輸出流。
FileOutputStream
類
OutputStream
有很多子類,我們從最簡單的一個子類開始。java.io.FileOutputStream
類是文件輸出流,用於將數據寫出到文件。
構造方法
public FileOutputStream(File file)
:創建文件輸出流以寫入由指定的 File對象表示的文件。
public FileOutputStream(String name)
: 創建文件輸出流以指定的名稱寫入文件。當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有這個文件,會創建該文件。如果有這個文件,會清空這個文件的數據。
public static void main(String[] args) {
// 使用File對象創建流對象
File file = new File("a.txt");
FileOutputStream fos1 = new FileOutputStream(file);
// 使用文件名稱創建流對象
FileOutputStream fos2 = new FileOutputStream("b.txt");
}
寫出字節數據
ASCII
字符代碼表
public void write(int b)
:將指定的字節輸出流。
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 寫出數據
fos.write(97); // 寫出第1個字節a
fos.write(98); // 寫出第2個字節b
fos.write(99); // 寫出第3個字節c
// 關閉資源
fos.close();
}
public void write(byte[] b)
:將b.length
字節從指定的字節數組寫入此輸出流。
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串轉換爲字節數組
byte[] b = "簡維程序員".getBytes();
// 寫出字節數組數據
fos.write(b);
// 關閉資源
fos.close();
}
☆
public void write(byte[] b, int off, int len)
:從指定的字節數組寫入len
字節,從偏移量off
開始輸出到此輸出流。☆
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串轉換爲字節數組
byte[] b = "abcde".getBytes();
// 寫出從索引2開始,2個字節。索引2是c,兩個字節,也就是cd。
fos.write(b,2,2);
// 關閉資源
fos.close();
}
數據的追加
public FileOutputStream(File file, boolean append)
: 創建文件輸出流以寫入由指定的 File對象表示的文件。
public FileOutputStream(String name, boolean append)
: 創建文件輸出流以指定的名稱寫入文件。
append
爲true
表示追加數據,false
表示清空原有數據,不寫默認爲false//源碼 public FileOutputStream(String name) throws FileNotFoundException { this(name != null ? new File(name) : null, false); } public FileOutputStream(File file) throws FileNotFoundException { this(file, false); }
寫出換行
回車符 \r 和換行符 \n :
回車符:回到一行的開頭(return)。
換行符:下一行(newline)。
系統中的換行
Windows系統裏,每行結尾是 回車+換行 ,即
\r\n
;Unix系統裏,每行結尾只有換行 ,即
\n
;Mac系統裏,每行結尾是 回車 ,即
\r
。
字節輸入流InputStream
java.io.InputStream
抽象類是表示字節輸入流的所有類的超類,可以讀取字節信息到內存中。它定義了字節輸入流的基本共性功能方法。
public void close()
:關閉此輸入流並釋放與此流相關聯的任何系統資源。public abstract int read()
: 從輸入流讀取數據的下一個字節。public int read(byte[] b)
: 從輸入流中讀取一些字節數,並將它們存儲到字節數組 b中 。
FileInputStream
類
java.io.FileInputStream
類是文件輸入流,從文件中讀取字節。
構造方法
FileInputStream(File file)
: 通過打開與實際文件的連接來創建一個FileInputStream
,該文件由文件系統中的 File對象 file命名。FileInputStream(String name)
: 通過打開與實際文件的連接來創建一個FileInputStream
,該文件由文件系統中的路徑名 name命名。- 當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有該文件,會拋出
FileNotFoundException
。
public static void main(String[] args) {
// 使用File對象創建流對象
File file = new File("a.txt");
FileInputStream fos = new FileInputStream(file);
// 使用文件名稱創建流對象
FileInputStream fos = new FileInputStream("b.txt");
}
讀取字節數據
public int read()
: 從輸入流讀取數據的下一個字節。
public static void main(String[] args) throws IOException{
FileInputStream fis = new FileInputStream("read.txt");
// 定義變量,保存數據
int b ;
// 循環讀取
while ((b = fis.read())!=‐1) {
System.out.println((char)b);
}
// 關閉資源
fis.close();
}
public int read(byte[] b)
: 從輸入流中讀取一些字節數,並將它們存儲到字節數組 b中 。
public static void main(String[] args) throws IOException{
// 使用文件名稱創建流對象.
FileInputStream fis = new FileInputStream("read.txt"); // 文件中爲abcde
// 定義變量,作爲有效個數
int len ;
// 定義字節數組,作爲裝字節數據的容器
byte[] b = new byte[2];
// 循環讀取
while (( len= fis.read(b))!=‐1) {
// 每次讀取後,把數組的有效字節部分,變成字符串打印
System.out.println(new String(b,0,len));// len 每次讀取的有效字節個數
}
// 關閉資源
fis.close();
}
//使用數組讀取,每次讀取多個字節,減少了系統間的IO操作次數,從而提高了讀寫的效率,建議開發中使用。
字節流練習–複製圖片
public class Copy {
public static void main(String[] args) throws IOException {
// 1.創建流對象
// 1.1 指定數據源
FileInputStream fis = new FileInputStream("D:\\test.jpg");
// 1.2 指定目的地
FileOutputStream fos = new FileOutputStream("test_copy.jpg");
// 2.讀寫數據
// 2.1 定義數組
byte[] b = new byte[1024];
// 2.2 定義長度
int len;
// 2.3 循環讀取
while ((len = fis.read(b))!=‐1) {
// 2.4 寫出數據
fos.write(b, 0 , len);
}
// 3.關閉資源
fos.close();
fis.close();
}
}
字符流Writer/Reader
當使用字節流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,那是因爲一箇中文字符可能佔用多個字節存儲。所以Java提供一些字符流類,以字符爲單位讀寫數據,專門用於處理文本文件。
字符輸出流Writer
java.io.Writer
抽象類是表示用於寫出字符流的所有類的超類,將指定的字符信息寫出到目的地。它定義了字節輸出流的基本共性功能方法。
public abstract void close()
:關閉此輸出流並釋放與此流相關聯的任何系統資源。
public abstract void flush()
:刷新此輸出流並強制任何緩衝的輸出字符被寫出。
public void write(int c)
:寫出一個字符。
public void write(char[] cbuf)
:將b.length
字符從指定的字符數組寫出此輸出流。
public abstract void write(char[] b, int off, int len)
:從指定的字符數組寫出len
字符,從偏移量off
開始輸出到此輸出流。
public void write(String str)
:寫出一個字符串。
FileWriter
類
java.io.FileWriter
類是寫出字符到文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。
構造方法
FileWriter(File file)
: 創建一個新的FileWriter
,給定要讀取的File對象。FileWriter(String fileName)
: 創建一個新的FileWriter
,給定要讀取的文件的名稱。當你創建一個流對象時,必須傳入一個文件路徑,類似於
FileOutputStream
。
public static void main(String[] args) throws IOException {
// 使用File對象創建流對象
File file = new File("a.txt");
FileWriter fw = new FileWriter(file);
// 使用文件名稱創建流對象
FileWriter fw = new FileWriter("b.txt");
}
寫出數據
public void write(int c)
:寫出一個字符。【注意】關閉資源時,與FileOutputStream不同。如果不關閉,數據只是保存到緩衝區,並未保存到文件。
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileWriter fw = new FileWriter("fw.txt");
// 寫出數據
fw.write(97); // 寫出第1個字符
fw.write('b'); // 寫出第2個字符
fw.write('C'); // 寫出第3個字符
fw.write(30000); // 寫出第4個字符,中文編碼表中30000對應 田。
/*
【注意】關閉資源時,與FileOutputStream不同。
如果不關閉,數據只是保存到緩衝區,並未保存到文件。
*/
fw.close();
}
關閉和刷新
因爲內置緩衝區的原因,如果不關閉輸出流,無法寫出字符到文件中。但是關閉的流對象,是無法繼續寫出數據的。如果我們既想寫出數據,又想繼續使用流,就需要 flush 方法了。
flush
:刷新緩衝區,流對象可以繼續使用。close
:關閉流,釋放系統資源。關閉前會刷新緩衝區。
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileWriter fw = new FileWriter("fw.txt");
// 寫出數據,通過flush
fw.write('刷'); // 寫出第1個字符
fw.flush();
fw.write('新'); // 繼續寫出第2個字符,寫出成功
fw.flush();
// 寫出數據,通過close
fw.write('關'); // 寫出第1個字符
fw.close();
fw.write('閉'); // 繼續寫出第2個字符,【報錯】java.io.IOException: Stream closed
fw.close();
}
寫出其它數據
write(char[] cbuf)
和write(char[] cbuf, int off, int len)
,每次可以寫出字符數組中的數據
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileWriter fw = new FileWriter("fw.txt");
// 字符串轉換爲字節數組
char[] chars = "簡維程序員".toCharArray();
// 寫出字符數組
fw.write(chars); // 簡維程序員
// 寫出從索引2開始,2個字節。索引2是'程',兩個字節,也就是'程序'。
fw.write(chars,2,2); // 程序
// 關閉資源
fos.close();
}
write(String str)
和write(String str, int off, int len)
,每次可以寫出字符串中的數據
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileWriter fw = new FileWriter("fw.txt");
// 字符串
String msg = "簡維程序員";
// 寫出字符數組
fw.write(msg); //簡維程序員
// 寫出從索引2開始,2個字節。索引2是'程',兩個字節,也就是'程序'。
fw.write(msg,2,2); // 程序
// 關閉資源
fos.close();
}
續寫和換行:操作類似於FileOutputStream。
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象,可以續寫數據
FileWriter fw = new FileWriter("fw.txt",true);
// 寫出字符串
fw.write("justweb");
// 寫出換行
fw.write("\r\n");
// 寫出字符串
fw.write("程序員");
// 關閉資源
fw.close();
}
字符流,只能操作文本文件,不能操作圖片,視頻等非文本文件。當我們單純讀或者寫文本文件時 使用字符流 其他情況使用字節流
字符輸入流Reader
java.io.Reader
抽象類是表示用於讀取字符流的所有類的超類,可以讀取字符信息到內存中。它定義了字符輸入流的基本共性功能方法。
public void close()
:關閉此流並釋放與此流相關聯的任何系統資源。public int read()
: 從輸入流讀取一個字符。public int read(char[] cbuf)
: 從輸入流中讀取一些字符,並將它們存儲到字符數組cbuf
中 。
FileReader
類
java.io.FileReader
類是讀取字符文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。
- 字符編碼:字節與字符的對應規則。Windows系統的中文編碼默認是GBK編碼表。idea中UTF-8
- 字節緩衝區:一個字節數組,用來臨時存儲字節數據。
構造方法
FileReader(File file)
: 創建一個新的FileReader
,給定要讀取的File對象。FileReader(String fileName)
: 創建一個新的FileReader
,給定要讀取的文件的名稱。當你創建一個流對象時,必須傳入一個文件路徑。類似於
FileInputStream
。
public static void main(String[] args) {
// 使用File對象創建流對象
File file = new File("a.txt");
FileReader fr = new FileReader(file);
// 使用文件名稱創建流對象
FileReader fr = new FileReader("b.txt");
}
讀取字符數據
public int read()
: 從輸入流讀取一個字符。
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileReader fr = new FileReader("read.txt");
// 定義變量,保存數據
int b ;
// 循環讀取
while ((b = fr.read())!=‐1) {
System.out.println((char)b);
}
// 關閉資源
fr.close();
};
public int read(char[] cbuf)
: 從輸入流中讀取一些字符,並將它們存儲到字符數組cbuf
中 。
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileReader fr = new FileReader("read.txt");
// 定義變量,保存有效字符個數
int len ;
// 定義字符數組,作爲裝字符數據的容器
char[] cbuf = new char[2];
// 循環讀取
while ((len = fr.read(cbuf))!=‐1) {
System.out.println(new String(cbuf));
}
// 關閉資源
fr.close();
}
/*
輸出結果:
簡維
程序
員序
*/
public static void main(String[] args) throws IOException {
// 使用文件名稱創建流對象
FileReader fr = new FileReader("read.txt");
// 定義變量,保存有效字符個數
int len ;
// 定義字符數組,作爲裝字符數據的容器
char[] cbuf = new char[2];
// 循環讀取
while ((len = fr.read(cbuf))!=‐1) {
System.out.println(new String(cbuf,0,len));
}
// 關閉資源
fr.close();
}
/*
輸出結果:
簡維
程序
員
*/