IO流的基本操作api方法 字元.位元組 輸入輸出的概念
IO流
什麼是IO
I input 輸入(讀取) 硬碟向記憶體輸入資料
O output輸出(寫入)記憶體向硬碟寫入資料
流:資料 (位元組/字元)1個字元=2個位元組,1個位元組=8個二進位制位
IO分類
根據資料的流向分為:輸入流和輸出流
-
輸入流:就是把資料從其他裝置上讀取到記憶體當中.
-
輸出流,就是把資料從記憶體當中寫入到其他裝置上的流.
根據資料的型別分為:位元組流和字元流
-
位元組流:以位元組為單位,讀寫資料的流
-
字元流:以字元為單位,讀寫資料的流
IO流的頂級父類
輸入流 | 輸出流 | |
---|---|---|
位元組流 | 位元組輸入流InputStream | 位元組輸出流OutputStream |
字元流 | 字元輸入流Reader | 字元輸出流Writer |
位元組流
一切皆為位元組
一切檔案資料(文字文件.圖片,視訊等)在儲存時,都是以二進位制數字的形式儲存的,都是一個一個的位元組,那麼資料在進行傳輸的時候也是如此.所以位元組流可以數傳任意檔案資料.在操作流程的時候,我們要明確,無論使用了什麼樣的流物件,底層傳輸的始終為二進位制資料.
位元組輸出流[OutputStream]
java.io.OutputStream此抽象類是表示輸出位元組流的所有類的超類,將指定的位元組資訊寫入到目的地,它定義了位元組輸出流的基本共性的api方法:
-
public void close():關閉此輸出流並釋放與此流相關的其他任何系統資源.
-
public void flush():重新整理此輸出流並強制任何緩衝的輸出位元組資訊被寫入.
-
public void writer(byt[] b):將b.length位元組從指定的自節陣列寫入到此輸出流中.
-
public void write(byte b,int off,int len):將指定的位元組陣列寫入len個位元組,從偏移量off開始輸出到此輸出流中
-
public abstract void write(int b):將指定的位元組輸出到此輸出流中.
FileOutputStream類
java.io.FileOutputStream類是檔案位元組輸出流,用於將資料寫入到檔案中.
構造方法
-
public FilePutStream(File file):建立一個向指定file物件則表示的檔案中寫入資料的檔案輸出流.
-
public FilePutStream(String name):建立檔案輸出流以指定的檔名稱寫入檔案中.
當你建立一個流物件時,必須西安傳遞一個檔案路徑,該路徑下,如果沒有這個檔案,會建立該檔案,如果有這個檔案.會清空這個檔案當中的資料,
FilePutOutStream作用:把記憶體當中的資料寫入到硬碟檔案中. 構造方法
- public FilePutStream(File file):建立一個向指定file物件則表示的檔案中寫入資料的檔案輸出流.
- public FilePutStream(String name):建立檔案輸出流以指定的檔名稱寫入檔案中.
引數:
File file:目的地是一個檔案
String name:目的地是一個檔案的路徑
構造方法的作用:
1.建立一個FileOutputStream類物件
2.會根據構造方法中傳遞的檔案/檔案路徑(路徑上檔案不存在),建立一個空的檔案.
3.會把FileOutputStream物件指向建立好的檔案.
位元組輸出流的使用步驟:
1.建立一個FileOutPutStream類物件,構造方法中傳遞寫入資料的目的地.
2.呼叫FileOutPutStream物件中的write方法.把資料寫入到檔案中.
3.釋放資源.
備註;任何記事本檔案在被開啟的時候,包括儲存方式都是以位元組的方式,所以讀取的時候採用的是本地字符集,whids系統採用的是GBK.
寫入資料的原理:
java成員-->JVM(java)虛擬機器-->OS(作業系統)-->OS呼叫作業系統中的寫入資料的方法-->把資料寫入到檔案中.
示例程式碼:
//1.建立一個FileOutPutStream類物件,構造方法中傳遞寫入資料的目的地.
FileOutputStream fos = new FileOutputStream("day28_IO\\a.txt");
//2.呼叫FileOutPutStream物件中的write方法.把資料寫入到檔案中.
fos.write(97);
//3.釋放資源
fos.close();
UTF-8 一個漢字佔三個位元組,GBK 一個漢字佔兩個位元組
資料的追加續寫
如何在保留目標檔案中的資料,還能繼續新增新的資料到目標檔案中?
-
public FileOutPutStream(File file,boolean append): 建立檔案輸出流以以寫入指定的File物件表示的檔案中.
-
public FileOutputStream(String name,boolean append):建立檔案輸出流以指定的名稱寫入檔案中.
這兩個構造方法,引數都需要傳入一個boolean型別的值,'true'表示追加資料 , 'false'表示清空原有資料.在這樣的情況下建立輸出流物件,就可以指定是否需要在檔案的末尾新增.
寫入換行
Windows系統裡面,換行符號是''\r\n'.把以指定是否需要追加續寫換行
Linux系統裡,換行符號是''/n'
mac系統裡,換行符號是'/r'
Unix系統裡,每行結尾只有換行,即\n
回車符\r和換行符\n
-
回車符:回到一行的開頭
-
換行符:下一行
系統中的換行:
-
Windows系統中,每行結尾是"回車+換行".即\r\n.
-
Unix系統中,每行的結尾只有換行,即\n
-
Mac系統中,每行的結尾是'回車',即\r
//1.建立物件
FileOutputStream fo = new FileOutputStream("day28_IO\\c.txt", true);
//實現資料換行
fo.write("\n".getBytes());
//2.呼叫write()方法
fo.write("HelloWord".getBytes());
//3.關閉流物件
fo.close();
位元組輸入流
java.io.unputStream此抽象類是表示位元組輸入流的所有類的超類,可以讀取位元組資訊到記憶體中,他定義了位元組輸入流的基本你的共性的api方法
-
public void close():關閉此輸入流並釋放與此流相關的其他的任何系統資源
-
public abstract int read():從輸入流中讀取資料的下一個位元組.
-
public int read(byte[] b):從輸入流中讀取一些位元組數,並將它們儲存到位元組陣列b當中
備註:close方法,當完成流的相關操作後,需要呼叫此方法關閉輸入流,釋放系統資源.
FileInputStream類
java.io.FileInputStream類是檔案輸入流,從檔案中讀取位元組.
構造方法
-
FileinputStream(Filoe file):通過開啟與實際檔案的連線來建立一個FileInputStream,該檔案有檔案系統中的File物件file命名.
-
FileInputStream(String name):通過開啟與實際檔案的連線來建立一個FileinputStream該檔案有檔案系統中的路徑名name命名. 引數: 讀取檔案的資料來源 String name: 檔案的路徑 File file: 檔案 構造方法的作用有兩個: 1.會建立一個FileInputStream類物件 2.會把FileInputStream類物件指定構造方法中要讀取的檔案 位元組輸入流的使用步驟: 1.建立一個FileInputStream類物件,構造方法中繫結要讀取的資料 2.使用FileInputStream類物件中方法read(),讀取檔案中的資料 3.釋放資源,關閉流物件
當你建立一個流物件時,必須穿入一個檔案路徑,該路徑下,如果沒有該檔案,會丟擲FileNotFoundException異常
使用read()方法讀取檔案中的位元組
int len=0;//表示記錄讀取到的位元組
while ((len=fi.read())!=-1)
System.out.print((char)len);
可以使用字元陣列來讀取資料:read(byte[] b):從輸入流中讀取多個位元組,並且將其儲存到緩衝區陣列b中,當讀取到檔案的末尾時,返回一個-1.
程式碼演示:
int len3=0;//記錄讀取到的有效位元組個數
byte[] bytes=new byte[1024];//2^10 1024b=1kb
while ((len3=fr.read(bytes))!=-1){
//byte[] 轉換成String
//String(byte[]byte,int offset,int length)
// System.out.println(new String(bytes, 0, len3));
System.out.println(new String(bytes));
}
備註:使用陣列讀取,每次可以讀取多個位元組,減少了系統間的IO操作次數,從而提高了讀取的效率,建議使用.
練習:圖片複製
通過位元組流實現圖片複製
實現從說面的G1.ipeq圖片複製到另一個目錄下
原理:從已知的檔案中讀取位元組,再把讀取到的位元組寫入到另一個檔案中.
//1.建立一個位元組輸入流物件FileInputStream,構造方法中繫結需要讀取的圖片路徑
FileInputStream fi = new FileInputStream("C:\\Users\\Administrator\\Desktop\\筆記\\Collection介面和Map介面概述.png");
//2.把檔案讀取出來
byte[] bytes = new byte[10240000];
// fi.read(bytes);
//建立位元組輸出流物件,FileOutPutStream,指向資料複製的目的地檔案地址
FileOutputStream f = new FileOutputStream("day28_IO\\c.png");
//方法1,直接放入整個byte陣列
// f.write(bytes);
//方法2
int len=0;
while ((len=fi.read(bytes))!=-1){
f.write(bytes,0,len);
}
f.close();
fi.close();
}
備註:流的關閉順序:先開後關,後開先關.
字元流
當使用位元組流讀取文字檔案的時候,肯能會引發一點小問題,如果你遇到中文字元時,可能不會顯示完整的字元.拿就是因為一箇中文字元可能佔用多個位元組儲存,所以java提供了一些字元流類,以字元為單位讀寫資料,專門用於處理文字文件檔案.
字元輸入流[Reader]讀取
java.io.Reader抽象類是表示用於讀取字元流的所有類的茶類,可以讀取字元資訊到記憶體當中,它定義了字元輸入流的基本共性的api方法:
-
public void close():關閉此輸入流並且釋放與此流相關的其他系統資源
-
public int read():從輸入流中讀取一個字元.
-
public int read(char[] ahuf):從輸入流中一次讀取多個字元,並將它們儲存到字元陣列chuf當中.
FileReader類
java.io.FileReader類主要是用於讀取字元檔案的便捷類.構造方法使用時的編碼字符集和預設的位元組緩衝區.
備註:
1.字元編碼:位元組與字元的對應規則.在windows系統中的中文編碼預設是GBK,idea中採用UTF-8
2.位元組緩衝去:一個自節陣列,用來臨時儲存位元組資料.
構造方法
-
FileReader(File file):建立一個新的FileReader物件,給定的指定的需要讀取的File物件.
-
FileReader(String filename):建立一個新的FileReader物件,指定需要讀取的檔名稱.
當你建立一個流物件時,必須闖入一個檔案路徑,類似於FileinputStream.
使用字元陣列讀取資料:read(char[] chuf),每次讀取chuf的長度個字元到陣列當中,返回讀取到有效字元的個數.當他讀取到末尾時,返回-1.
程式碼例項:
//建立物件,構造方法中繫結資料來源
FileReader fi = new FileReader("day28_IO\\c.txt");
//2.呼叫read方法
char[] chuf = new char[1024];
int len=0;//記錄的是每次轉換的有效的字元個數
while ((len=fi.read(chuf))!=-1){
//字元陣列轉換成字串
//String static valueOf()
System.out.println(new String(chuf,0,len));
}
//3.釋放資源
fi.colse();
字元輸出流[Wruter]
java.io.Writer抽象類是表示用於寫入(輸出)字元流的所有類的超類.將指定的字元資訊寫入到目的地中.他同時定義了字元輸出流的基本共性的API方法:
-
void write(int c):寫入單個字元
-
void write(char[] chuf):寫入字元陣列
-
abstract void write(char[] chuf,int off,int len):寫入char陣列的一部分從off(起始索引值)開始,寫入len個字元個數.
-
void write(String str):寫入字串.
-
void write(String str,int off,int len):寫入字串的一部分,從字串的起始索引off開始,寫入len個字元
-
void flush():重新整理
-
void close():關閉此流,但是需要先重新整理它.
FileWriter類
'java.io.FileWriter'類是用於寫入字元到檔案中,構造方法使用系統預設的字元編碼和預設的位元組緩衝區.
構造方法
-
FileWriter(File file):建立一個新的FileWriter,指定寫入的file物件
-
FileWriter(String name):建立一個新的FileWriter,指定需要寫入的檔案的名稱.
當你建立一個流物件時,必須傳入一個檔案路徑,類似於FileOutputStream.
示例:
FileWriter fi = new FileWriter("day28_IO\\b.txt");
//2.使用FileWriter賭俠凝重的方法Write.把資料寫入到記憶體緩衝區中(字元轉換為位元組的過程)
//void write(int c)寫入單個字元
fi.write(107);//J
//3.使用FileWriter物件的中的方法flush,把記憶體緩衝區中的資料重新整理到檔案中.
// fi.flush();
//4.釋放資源(會先把記憶體緩衝區中的資料重新整理到檔案中)
fi.close();
關閉和重新整理
因為內建緩衝區的原因,如果不關閉輸出流,無法寫入字元到檔案中.但是關閉流物件,是無法繼續寫入資料到檔案中.如果既想寫入資料到檔案中,又想繼續使用流物件,那麼就需要flush方法.
-
flush:重新整理緩衝區的資料,流物件可以繼續使用
-
close:先重新整理緩衝區,然後會通知系統釋放資源,關閉流物件,流物件不可以再使用
程式碼
//1.建立物件
FileWriter fi = new FileWriter("day28_IO\\e.txt");
//2.呼叫write方法.
fi.write(97);//a
//3.重新整理緩衝區
fi.flush();//把緩衝區的資料重新整理到檔案中
//重新整理之後流還可以繼續使用
fi.write(98);
//4.關閉流物件
fi.close();
//close方法之後,流已經關閉了,從記憶體中消失了,流不能再使用了,如果還用會異常
//java.io.IOException: Stream closed
fi.write(99);
寫入字元陣列:'write(char[] chuf)和write(char[] chuf,int off,ing len)',每次可以寫入一個字元陣列
用法類似FileOutputSrearm
續寫和換行:操作類似於FileOutPutStream
//1.new
FileWriter fi = new FileWriter("day28_IO\\g.txt", true);
//write
char[] chars =new char[50];
for (int i = 0; i < 50; i++) {
chars[i]=(char)(8140+i);
fi.write(chars[i]+"\r\n");//
}
//flush
fi.flush();
//關閉流
fi.close();
}
備註:字元流,只能操作文字檔案,不能操作圖片,視訊等非文字檔案.
所以當我們單純的就是想操作文字檔案,就是用字元流,其他情況一律使用位元組流.
IO異常的處理
JDK1.7之前的處理,
FileWriter fw=null;
try {
//可能會產生異常
fw = new FileWriter("day28_IO\\g.txt", true);
//2.write
fw.write(97);
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}
//重新整理
finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
之後可以把流的操作放入try的小擴號裡面 新特性,try後面可以跟進一個小括號,並且放入小括號的流會在try catch結束後自動釋放流
在JDK1.7之前使用try...catch...finally 處理流中的異常 格式: try{ //可能會發生的異常 }catch(異常型別 一場變數名){ 異常的處理邏輯}finally{ //釋放系統資源 並且finally語句塊一定會被執行 }
JDK7新特性
.可以使用try-with-resource語句,該語句確保了每個資源在語句結束時關閉,所謂的資源(resource)是指在程式完成後,必須要關閉的物件.
格式:
try(建立流物件語句,如果多個,請用";"隔開){
//可能會產生異常的程式碼
}catch(異常型別 一場變數名){
//異常處理邏輯
}
程式碼如下:
try ( //1.1new
FileOutputStream fi = new FileOutputStream("day28_IO\\g.txt");
//1.2new
final FileInputStream fw = new FileInputStream("day28_IO\\a.txt"))
{ //2. write
int len=0;
while ((len=fw.read())!=-1){
fi.write(len);
}
}catch (IOException e){
//異常的處理邏輯
e.printStackTrace();
}