文章目錄
IO流
一切皆爲字節
一切文件數據(文本、圖片、視頻等)在存儲時,都是以二進制數字的形式保存,都一個一個的字節,那麼傳輸時一樣如此。所以,字節流可以傳輸任意文件數據。在操作流的時候,我們要時刻明確,無論使用什麼樣的流對象,底層傳輸的始終爲二進制數據。
字節輸出流【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)
:將指定的字節輸出流。
注意:
close方法,當完成流的操作時,必須調用此方法,釋放系統資源。
FileOutputStream類
OutputStream
有很多子類,我們從最簡單的一個子類開始。
java.io.FileOutputStream
類是文件輸出流,用於將數據寫出到文件。
構造方法
public FileOutputStream(File file)
:創建文件輸出流以寫入由指定的 File對象表示的文件。public FileOutputStream(String name)
: 創建文件輸出流以指定的名稱寫入文件。
當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有這個文件,會創建該文件。如果有這個文件,會清空這個文件的數據。
寫出字節數據
- 寫出字節:
write(int b)
方法,每次可以寫出一個字節數據
小貼士:
- 雖然參數爲int類型四個字節,但是隻會保留一個字節的信息寫出。
- 流操作完畢後,必須釋放系統資源,調用close方法,千萬記得。
-
寫出字節數組:
write(byte[] b)
,每次可以寫出數組中的數據 -
寫出指定長度字節數組:
write(byte[] b, int off, int len)
,每次寫出從off索引開始,len個字節
代碼演示
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class Demo02OutPutStream {
public static void main(String[] args) throws IOException {
//創建FileOutputStream對象。
FileOutputStream fos = new FileOutputStream("D:\\b.txt");
//創建byte數組
byte[] byte1 = {65,66,67,68,69};
//當字節是在(1~127)之間時按照ASCII表寫入數據,
//如果第一個字節爲負數,那第一個字節和第二個字節組成一箇中文顯示,查詢系統默認碼錶(GBK)
fos.write(byte1);//ABCDE
/*public void write(byte b[], int off, int len)
int off:數據的開始索引
int len:寫幾個字節
*/
//從數組byte1的1號字節開始寫2個字節
fos.write(byte1,1,2);//BC
//將字符串轉換爲字節數組
byte[] byte2 = "你好".getBytes();
//輸出字符串轉換的字節數組
System.out.println(Arrays.toString(byte2));//[-28, -67, -96, -27, -91, -67]
//將字節數組輸出
fos.write(byte2);
////釋放資源(流使用會佔用一定的內存,使用完畢要把內存清空,提高程序的效率)
fos.close();
}
}
在給定的路徑下新創建了一個b.txt文件
寫入的文件內容
你好的字節數組
注:UTF-8編碼,三個字節表示一個漢字;GBK編碼,兩個字節表示一個漢字。
數據追加續寫
經過以上的演示,每次程序運行,創建輸出流對象,都會清空目標文件中的數據。如何保留目標文件中數據,還能繼續添加新數據呢?
public FileOutputStream(File file, boolean append)
: 創建文件輸出流以寫入由指定的 File對象表示的文件。public FileOutputStream(String name, boolean append)
: 創建文件輸出流以指定的名稱寫入文件。
這兩個構造方法,參數中都需要傳入一個boolean類型的值,true
表示追加數據,false
表示清空原有數據。這樣創建的輸出流對象,就可以指定是否追加續寫了
寫出換行
Windows系統裏,換行符號是\r\n
。
- 回車符
\r
和換行符\n
:
- 回車符:回到一行的開頭(return)。
- 換行符:下一行(newline)。
- 系統中的換行:
- Windows系統裏,每行結尾是
回車+換行
,即\r\n
;- Unix系統裏,每行結尾只有
換行
,即\n
;- Mac系統裏,每行結尾是
回車
,即\r
。從 Mac OS X開始與Linux統一。
代碼演示
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo03OutPutStream {
public static void main(String[] args) throws IOException {
//append 爲true時創建對象不會覆蓋源文件,繼續在文件末尾追加數據
//爲false時創建一個新文件,覆蓋源文件。
FileOutputStream fos = new FileOutputStream("D:\\c.txt",true);
byte[] bytes1 = "你好".getBytes();
byte[] bytes2 = "世界".getBytes();
//換行
byte[] bytes = "\r\n".getBytes();
//寫入換行
fos.write(bytes);
//寫入你好
fos.write(bytes1);
//寫入換行
fos.write(bytes);
fos.write(bytes2);
//釋放資源
fos.close();
}
}
字節輸入流【InputStream】
java.io.InputStream
抽象類是表示字節輸入流的所有類的超類,可以讀取字節信息到內存中。它定義了字節輸入流的基本共性功能方法。
public void close()
:關閉此輸入流並釋放與此流相關聯的任何系統資源。public abstract int read()
: 從輸入流讀取數據的下一個字節。public int read(byte[] b)
: 從輸入流中讀取一些字節數,並將它們存儲到字節數組 b中 。
小貼士:
close方法,當完成流的操作時,必須調用此方法,釋放系統資源。
FileInputStream類
java.io.FileInputStream
類是文件輸入流,從文件中讀取字節。
構造方法
FileInputStream(File file)
: 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的 File對象 file命名。FileInputStream(String name)
: 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的路徑名 name命名。
當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有該文件,會拋出FileNotFoundException
。
讀取字節數據
- 讀取字節:
read
方法,每次可以讀取一個字節的數據,提升爲int類型,讀取到文件末尾,返回-1
,
代碼演示
import java.io.FileInputStream;
import java.io.IOException;
public class Demo01InPutStream {
public static void main(String[] args) throws IOException {
//創建FileInputStream對象
FileInputStream fis = new FileInputStream("D:\\a.txt");
int len = 0;
//循環讀取文件
//當文件讀取到末尾時會返回-1,所以當len= -1時結束循環
while (( len = fis.read()) != -1 ){
//len本身輸出的是abc的字節編碼,強轉爲char後變爲 a b c
System.out.print((char)len+" "); //a b c
System.out.println(len);//97 98 99
}
fis.close();
}
}
注意:
- 雖然讀取了一個字節,但是會自動提升爲int類型。
- 流操作完畢後,必須釋放系統資源,調用close方法,千萬記得。
- 使用字節數組讀取:
read(byte[] b)
,每次讀取b的長度個字節到數組中,返回讀取到的有效字節個數,讀取到末尾時,返回-1
,代碼使用演示:
import java.io.FileInputStream;
import java.io.IOException;
public class Demo02InPutStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\a.txt");
//創建字節數組,一次讀取2個字節。 一般爲1024的倍數。
byte[] b = new byte[2];
int len = 0;
//循環讀取
//一次讀取2個字節
while ((len = fis.read(b))!=-1){
System.out.println(new String(b));//String(byte b) 可以將字節轉換爲字符串
}
//釋放資源
fis.close();
}
}
錯誤數據d
,是由於最後一次讀取時,只讀取一個字節e
,數組中,上次讀取的數據沒有被完全替換,所以要通過len
,獲取有效的字節,代碼使用演示:
import java.io.FileInputStream;
import java.io.IOException;
public class Demo02InPutStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\a.txt");
//創建字節數組,一次讀取2個字節
byte[] b = new byte[2];
int len = 0;
//循環讀取
//一次讀取2個字節
while ((len = fis.read(b))!=-1){
System.out.println(new String(b,0,len));//可以將字節轉換爲字符串,0表示從第0個字節開始,len表示長度
}
//釋放資源
fis.close();
}
}
注意:
使用數組讀取,每次讀取多個字節,減少了系統間的IO操作次數,從而提高了讀寫的效率,建議開發中使用。
字節流練習:圖片複製
複製原理圖解
案例實現
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
//創建一個字節輸入流對象,構造方法中綁定要讀取的數據源
FileInputStream fis = new FileInputStream("C:\\1.png");
//創建一個字節輸出流對象,構造方法中綁定要寫入的目的地
FileOutputStream fos = new FileOutputStream("D:\\2.png");
int len = 0;
//使用數組讀取多個字節,寫入多個字節
byte[] bytes = new byte[1024];
//使用字節輸入流中的方法read讀取文件
while ((len = fis.read(bytes))!=-1){
//使用字節輸出流中的方法read讀取文件
fos.write(bytes,0,len);
}
fis.close();
fos.close();
}
}