1.本文概述
本文講解IO系列有關字節流對象部分的內容。
字節流主要包含以下四個部分:
FileOutputStream
FileInputStream
BufferedOutputStream
BufferedinputStream
2.字節流的輸出操作
1.輸出流OutputStream
常用方法:
void close()
關閉此輸出流並釋放與此流有關的所有系統資源。
void flush()
刷新此輸出流並強制寫出所有緩衝的輸出字節。
void write(byte[] b)
將 b.length 個字節從指定的 byte 數組寫入此輸出流。
void write(byte[] b, int off, int len)
將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。
abstract void write(int b)
將指定的字節寫入此輸出流。
說明:OutputStream是一個抽象類,無法直接實例化,因此一般使用其直接子類FileOutputStream。
2.文件輸出流FileOutputStream
構造方法:
FileOutputStream(File file)
創建一個向指定 File 對象表示的文件中寫入數據的文件輸出流。
FileOutputStream(File file, boolean append)
創建一個向指定 File 對象表示的文件中寫入數據的文件輸出流。如果爲append爲true,則將字節寫入文件末尾處,而不是覆蓋整個文件。
FileOutputStream(String name)
創建一個向具有指定名稱的文件中寫入數據的輸出文件流。
FileOutputStream(String name, boolean append)
創建一個向具有指定 name 的文件中寫入數據的輸出文件流。
常用方法:
void close()
關閉此文件輸出流並釋放與此流有關的所有系統資源。
void write(byte[] b)
將 b.length 個字節從指定 byte 數組寫入此文件輸出流中。
void write(byte[] b, int off, int len)
將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此文件輸出流。
void write(int b)
將指定字節寫入此文件輸出流。
void close()
關閉此輸出流並釋放與此流有關的所有系統資源。
需求描述:將字符串數據以字節流的形式寫入指定文件中
示例代碼:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) {
//聲明FileOutputStream對象
FileOutputStream fos=null;
try {
//實例化FileOutputStream對象
fos=new FileOutputStream("G:\\file_out_test.txt");
//用於輸出的目標字符串
String tarStr="這是通過字節流寫入文件的測試數據";
//以字節流的輸出目標字符串
fos.write(tarStr.getBytes());
//刷新字節流緩存
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fos!=null)
try {
//關閉字節流
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
程序運行結果
4.png
3.字節流的讀取操作
1.輸入流InputSteam
常用方法:
int available()
返回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀取(或跳過)的估計字節數。
void close()
關閉此輸入流並釋放與該流關聯的所有系統資源。
abstract int read()
從輸入流中讀取數據的下一個字節。
int read(byte[] b)
從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組 b 中。
int read(byte[] b, int off, int len)
將輸入流中最多 len 個數據字節讀入 byte 數組。long skip(long n)
跳過和丟棄此輸入流中數據的 n 個字節。
說明:FileInputStream是一個抽象類,無法直接實例化,因此一般使用其直接子類FileInputStream。
2.文件輸入流FileInputStream
構造方法:
FileInputStream(File file)
通過打開一個到實際文件的連接來創建一個 FileInputStream,該文件通過文件系統中的 File 對象 file 指定。
FileInputStream(String name)
通過打開一個到實際文件的連接來創建一個 FileInputStream,該文件通過文件系統中的路徑名 name 指定。
常用方法:
int available()
返回下一次對此輸入流調用的方法可以不受阻塞地從此輸入流讀取(或跳過)的估計剩餘字節數。
void close()
關閉此文件輸入流並釋放與此流有關的所有系統資源。
int read()
從此輸入流中讀取一個數據字節。
int read(byte[] b)
從此輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中。
int read(byte[] b, int off, int len)
從此輸入流中將最多 len 個字節的數據讀入一個 byte 數組中。
long skip(long n)
從輸入流中跳過並丟棄 n 個字節的數據。
第一種方式:
//部分代碼
public static void main(String[] args) {
//聲明FileInputStream對象
FileInputStream fis=null;
try {
//實例化FileInputStream對象
fis=new FileInputStream("G:\\file_out_test.txt");
int ch=0;
while((ch=fis.read())!=-1){
//將獲取到的int型數據強轉爲char型輸出
System.out.print((char)ch);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally{
if(fis!=null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
程序運行結果:
test:this file is used by OutputStream
說明:使用這種方式讀取數據,目標文件中不能存在中文,否則會出現亂碼。因爲無參構造方法每次只會讀取單個字節,而每個中文由兩個字節組成
第二種方式:
//部分代碼
public static void main(String[] args) {
//聲明FileInputStream對象
FileInputStream fis=null;
try {
//實例化FileInputStream對象
fis=new FileInputStream("G:\\file_out_test.txt");
//定義用於臨時存儲數據的字節數組,請區別於FileReader的字符數組
byte[] bufArr=new byte[1024];
//記錄讀取到的字符數組長度
int len;
while((len=fis.read(bufArr))!=-1){
System.out.println(new String(bufArr,0,len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally{
if(fis!=null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
程序運行結果:
test:this file is used by OutputStream
test:這裏使用了字節數組作爲緩衝區
tsst:所以我終於可以出現中文了
第三種方式-特有方式
示例代碼:
//部分代碼
public static void main(String[] args) {
//聲明FileInputStream對象
FileInputStream fis=null;
try {
//實例化FileInputStream對象
fis=new FileInputStream("G:\\file_out_test.txt");
//建立和目標文件字節流大小一致的字節數組
byte[] bufArr=new byte[fis.available()];
//讀取字節流
fis.read(bufArr);
//將字節數組轉化爲字符串輸出
System.out.println(new String(bufArr));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally{
if(fis!=null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
程序運行結果
test:this file is used by OutputStream
test:這裏使用了字節數組作爲緩衝區
tsst:所以我終於可以出現中文了
說明:這種方式只適用於文件較小的情況,因爲java虛擬機初始化時的默認內存僅爲64M
總結:考慮到實際開發中的效率要求,建議使用第二種方式。
4.拷貝圖片
需求描述:將G盤根目錄下的測試圖片複製到D盤
步驟:
1.用字節讀取流對象和圖片文件關聯
2.用字節寫入流對象創建一個圖片文件,用於存儲獲取到的圖片數據
3.通過循環讀寫,完成數據存儲
4.關閉資源
示例代碼:
//部分代碼
public static void main(String[] args) {
//聲明字節輸入輸出流對象
FileOutputStream fos=null;
FileInputStream fis=null;
try {
//進行實例化
fos=new FileOutputStream("D:\\test.png");
fis=new FileInputStream("G:\\test.png");
//臨時存儲數據的緩衝數組
byte[] bufArr=new byte[1024];
//記錄讀取的數據長度
int len;
while((len=fis.read(bufArr))!=-1){
fos.write(bufArr, 0, len);
fos.flush();//刷新流緩存
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fis!=null)
try {
//關閉流
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
if(fos!=null)
try {
//關閉流
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5.字節流的緩衝區
對應類:
BufferedOutputStream
BufferedInputStream
1.緩衝輸出流
構造方法:
BufferedOutputStream(OutputStream out)
創建一個新的緩衝輸出流,以將數據寫入指定的底層輸出流。
BufferedOutputStream(OutputStream out, int size)
創建一個新的緩衝輸出流,以將具有指定緩衝區大小的數據寫入指定的底層輸出流。
常用方法:
void flush()
刷新此緩衝的輸出流。
void write(byte[] b, int off, int len)
將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此緩衝的輸出流。
void write(int b)
將指定的字節寫入此緩衝的輸出流。
void close()
關閉此輸出流並釋放與此流有關的所有系統資源。
void write(byte[] b)
將 b.length 個字節寫入此輸出流。
2.緩衝輸入流
構造方法:
BufferedInputStream(InputStream in)
創建一個 BufferedInputStream 並保存其參數,即輸入流 in,以便將來使用。
BufferedInputStream(InputStream in, int size)
創建具有指定緩衝區大小的 BufferedInputStream 並保存其參數,即輸入流 in,以便將來使用。
常用方法:
int available()
返回可以從此輸入流讀取(或跳過)、且不受此輸入流接下來的方法調用阻塞的估計字節數。
void close()
關閉此輸入流並釋放與該流關聯的所有系統資源。
int read()
參見 InputStream 的 read 方法的常規協定。
int read(byte[] b)
從此輸入流中將 byte.length 個字節的數據讀入一個 byte 數組中。
int read(byte[] b, int off, int len)
從此字節輸入流中給定偏移量處開始將各字節讀取到指定的 byte 數組中。long skip(long n)
跳過和丟棄此輸入流中數據的 n 個字節。
3.簡單應用
需求描述:將G盤的MP3文件通過緩衝字節流複製到D盤
示例代碼:
//部分代碼
public static void main(String[] args) {
long start=System.currentTimeMillis();
//聲明輸入輸出緩衝字節流對象
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
//實例化對象
bis=new BufferedInputStream(new FileInputStream("G:\\test.mp3"));
bos=new BufferedOutputStream(new FileOutputStream("D:\\test.mp3"));
//寫入數據
byte[] b=new byte[1024];
int len=0;
while((len=bis.read(b))!=-1){
bos.write(b, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally{
if(bos!=null)
try {
//關閉流
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
if(bis!=null)
try {
//關閉流
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
long end=System.currentTimeMillis();
System.out.println("消耗時間:"+(end-start)+"ms");
}
}
程序運行結果
消耗時間:13ms
說明:在本例中可以不使用flush進行刷新。並且因爲緩衝流的應用,文件的複製效率得到了大幅度提高