字節流(InputStream和OutputStream)
輸入流(InputStream):
- 概述:
- 此抽象類是表示字節輸入流的所有類的超類, 因爲是抽象類,不能直接實例化,所以必須使用其子類進行實例化(常用實現類:FileInputStream)。
常用方法:
read();
從輸入流中讀取數據的下一個字節。read(byte[] b);
從輸入流中讀取一定數量的字節,並將其存儲在緩衝區數組 b 中。read(byte[] b, int off, int len);
將輸入流中最多 len 個數據字節讀入 byte 數組。close();
關閉此輸入流並釋放與該流關聯的所有系統資源。
基本字節流操作(僞代碼演示):
//創建輸入流對象
InputStream fis = new FileInputStream("b.txt");
//方式1
int by = 0; //定義變量,記錄每次讀到的字節
while ((by = fis.read()) != -1) { //將每次讀到的字節賦值給b並判斷是否是-1
System.out.println(by);
}
//方式2
byte[] bys = new byte[1024]; //自定義數組
int len = 0;
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));//寫出有效的字節個數
}
//釋放資源
fis.close();
- 注意:
- 1):read():讀一個,光標就在下一行等着讀下一個,讀完後光標就放到了最後,再讀就沒了,這時會返回 -1,和集合裏面迭代器的next() 有點相似。
- 2);當用字節流讀漢字並打印到控制檯上,有時候會出現 “??” 問題,是因爲漢字是由兩個字節組成的,每次讀一個字節,所以就會出現”??”的現象,但是此問題用字節流複製文本文件時不會出現。
輸出流(OutPutStream):
基本字節流操作
基本字節輸出流的操作
A:創建字節輸出流對象
FileOutputStream fos = new FileOutputStream(“a.txt”);
注意:輸出流輸出數據在創建輸出流對象的時候,如果文件不存在,就創建一個如果存在就清空該文件數據,然後寫入數據。B:調用寫數據的方法
fos.write(97);C:釋放資源
fos.close();注意:寫數據的方法有
write(byte b)
write(byte[] bys);
write(byte[] bys, int start,int lenth);
追加寫入用兩個參數構造
FileOutputStream fos = new FileOutputStream(“a.txt”,true);
字節流複製文件的幾種方法:
- 普通字節流複製文件 一次一個字節數據:
FileInputStream fis = new FileInputStream("123.jpg"); //創建輸入流對象,關聯123.jpg
FileOutputStream fos = new FileOutputStream("copy.jpg");//創建輸出流對象,關聯copy.jpg
int b;
while((b = fis.read()) != -1) { //在不斷的讀取每一個字節
fos.write(b); //將每一個字節寫出
}
//關流釋放資源
fis.close();
fos.close();
- 普通字節流複製文件 一次性拷貝一整個文件:
FileInputStream fis = new FileInputStream("致青春.mp3");
FileOutputStream fos = new FileOutputStream("copy.mp3");
byte[] arr = new byte[fis.available()]; //創建與文件一樣大小的字節數組(如果文件過大,會造成內存溢出)
fis.read(arr); //將文件上的字節讀取到內存中
fos.write(arr); //將字節數組中的字節數據寫到文件上
fis.close();
fos.close();
- 普通字節流複製文件 一次一個字節數組:
FileInputStream fis = new FileInputStream("致青春.mp3");
FileOutputStream fos = new FileOutputStream("copy.mp3");
byte[] arr = new byte[1024 * 8]; //一般就定義成8kb的大小
int len; //len是讀到的有效字節個數
while((len = fis.read(arr)) != -1) { //寫arr是將文件上的字節讀取到字節數組中,
//如果忘記加arr,返回的就不是讀取的字節個數,而是字節的碼錶值
fos.write(arr,0,len); //0表示是從數組的0索引開始 len表示寫入數組的0-len長度的數據
}
fis.close();
fos.close();
- 高效字節流複製文件:
//高效字節流就是包裝了一下普通字節流,內置了一個緩衝區(數組,大小是8kb)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("致青春.mp3"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp3"));
int b;
while((b = bis.read()) != -1) {
bos.write(b);
}
bis.close();
bos.close();
close()和flush()方法的區別:
close():關閉流 並且在關閉流之前刷新一次緩存區 而且關閉了之後就不能再使用流了。
flush(): 只刷新緩充區 不關閉流 流還可以繼續使用。
字節流注意問題:
- 字節流讀取中文的問題:
- 字節流在讀中文並打印到控制檯的時候有可能會讀到半個中文,造成亂碼。
- 字節流寫出中文的問題:
- 字節流直接操作的字節,所以寫出中文必須將字符串轉換成字節數組 fos.write(“我讀書少,你不要騙我”.getBytes());
- 寫出回車換行 write(“\r\n”.getBytes());
JDK1.6複製文件加入標準異常處理代碼:
FileInputStream fis = null;
FileOutputStream fos = null;
try{
fis = new FileInputStream("xxx.txt");
fos = new FileOutputStream("copy.txt");
int len;
while((len = fis.read()) != -1) {
fos.write(len);
}
}finally {
try { //try fianlly的嵌套目的是能關一個儘量關一個
if(fis != null)
fis.close();
} finally{
if(fos != null)
fos.close();
}
}
JDK1.7複製文件加入標準異常處理代碼:
try(
FileInputStream fis = new FileInputStream("xxx.txt");
FileOutputStream fos = new FileOutputStream("copy2.txt");
){
int len;
while((len = fis.read()) != -1) {
fos.write(len);
}
}