首先得搞清楚兩個概念:什么是輸入流與輸出流莽鸭?什么是字節(jié)流與字符流?
1.是從程序的角度出發(fā)珠移。輸入是程序得到外部數(shù)據(jù),輸出是程序向外部傳輸數(shù)據(jù)。
2.個人理解字節(jié)流與字符流钧惧,字節(jié)流是按字節(jié)讀取暇韧,字符流實際上是根據(jù)指定編碼按照字節(jié)讀取然后將其解碼為字符流。得到就是字符流對象浓瞪。使用字節(jié)流可以讀取所有文件懈玻,而字符流適用于文本文件。
下面進行詳細介紹:
一乾颁、字節(jié)流
字節(jié)輸出流OutputStream
OutputStream是將內(nèi)存中的數(shù)據(jù)寫出到文件中
OutputStream:字節(jié)輸出流涂乌,抽象類。是輸出字節(jié)流的所有類的超類
FileOutputstream 文件輸出流 是OutputStream的子類英岭,就針對于寫入文件的流
File f1 = new File("C:\\myPicture\\1.txt");
try {
FileOutputStream fileOutputStream = new FileOutputStream("C:\\myPicture\\1.txt");
fileOutputStream.write("你好".getBytes());
fileOutputStream.close();//注意流的關(guān)閉
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//以上注意是將“你好”寫入"C:\\myPicture\\1.txt"當(dāng)中湾盒。
2.給文件中續(xù)寫和換行
我們直接newFileOutputStream(file)這樣創(chuàng)建對象,寫入數(shù)據(jù)诅妹,會覆蓋原有的文件罚勾,那么我們想在原有的文件中續(xù)寫內(nèi)容怎么辦呢?
繼續(xù)查閱FileOutputStream的API吭狡。發(fā)現(xiàn)在FileOutputStream的構(gòu)造函數(shù)中尖殃,可以接受一個boolean類型的值,如果值true划煮,就會在文件末位繼續(xù)添加分衫。
FileOutputStream fileOutputStream2 = new FileOutputStream("C:\\myPicture\\1.txt",true);
fileOutputStream2.write("張慧".getBytes());
fileOutputStream2.close();//此時1.txt中的內(nèi)容就變成了“你好張慧”。
IO異常的處理
在前面編寫代碼中都發(fā)生了IO的異常般此。我們在實際開發(fā)中,對異常時如何處理的牵现,我們來演示一下铐懊。
publicclassFileOutputStreamDemo3 {
publicstaticvoidmain(String[] args) {
File file =newFile("c:\\file.txt");
//定義FileOutputStream的引用
FileOutputStream fos =null;
try{
//創(chuàng)建FileOutputStream對象
fos=newFileOutputStream(file);
//寫出數(shù)據(jù)
fos.write("abcde".getBytes());
}catch(IOException e) {
System.out.println(e.toString()+"----");
}finally{
//一定要判斷fos是否為null,只有不為null時瞎疼,才可以關(guān)閉資源
if(fos !=null){
try{
fos.close();
}catch(IOException e) {
thrownewRuntimeException("");
}}}}}
字節(jié)輸入流InputStream
InputStream是將文件中的數(shù)據(jù)讀取到內(nèi)存中科乎。抽象類。它是字節(jié)輸出流的所有類的超類贼急。
read() ---abstract int 從輸入流中讀取數(shù)據(jù)的下一個字節(jié)茅茂。
read(byte[ ] b)----int從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲在緩沖區(qū)數(shù)組b中太抓。
InputStream有很多子類空闲,其中子類FileInputStream可用來讀取文件內(nèi)容。
FileInputStream從文件系統(tǒng)中的某個文件中獲得輸入字節(jié)走敌。
方法 read()與read(byte【】)
read()返回的是當(dāng)前讀取自己的ASCII碼值
一個字節(jié)一個字節(jié)的從文件讀取到內(nèi)存碴倾,返回值是每一個字節(jié)(當(dāng)前讀取字節(jié))的ASCII值0——255,如果到達流的尾部,則返回為-1跌榔,由于中文文字是兩個字節(jié)异雁,所以這里就會出現(xiàn)亂碼問題。如下1.txt里面內(nèi)容為“你好baby”
FileInputStream fileInputStream = new FileInputStream("C:\\myPicture\\1.txt");
int read = 0;
System.out.println("read----"+read);
while((read=fileInputStream.read())!=-1){
System.out.println("read---"+read);//一串?dāng)?shù)字
System.out.println((char)read);//不能輸出中文僧须,會亂碼
}//打印結(jié)果為:一串?dāng)?shù)字纲刀。英文為其對應(yīng)的ASCII值239 187 191 228 189 160 229 165 189 98 97 98 121中文部分其實是兩個字節(jié),只要把這些字節(jié)去查閱對應(yīng)的編碼表担平,就能夠得到與之對應(yīng)的字符示绊。API中是否給我們已經(jīng)提供了讀取相應(yīng)字符的功能流對象,Reader驱闷,讀取字符流的抽象超類耻台。
read(byte【】)返回的是實際讀取的字節(jié)數(shù),并將讀取的數(shù)據(jù)存入緩存byte數(shù)組里
為了解決中文讀取亂碼的問題空另,所以read(byte【】)是一下子讀取一定數(shù)量的字節(jié)盆耽。返回值是實際上讀取的字節(jié)數(shù)
FileInputStream fileInputStream = new FileInputStream("C:\\myPicture\\1.txt");
int read = 0;
byte[] b = new byte[1024];//一下子讀取1024個字節(jié)
while((read=fileInputStream.read(b))!=-1){
System.out.println(new String(b,0,read));
}
fileInputStream.close();//關(guān)流
打印結(jié)果:你好baby
文件的復(fù)制
方法一://一個字節(jié)一個自己的讀與寫,輸入流和輸出流之間是通過read這個變量進行數(shù)據(jù)交換的扼菠。效率低下
FileInputStream fileInputStream = new FileInputStream("C:\\myPicture\\1.txt");
FileOutputStream fileOutputStream = new FileOutputStream("C:\\myPicture\\a.txt");
int read = 0;
byte[] b = new byte[1024];
while((read=fileInputStream.read())!=-1){
fileOutputStream.write(read);
}
fileInputStream.close();//關(guān)流
fileOutputStream.close();
緩沖數(shù)組方式復(fù)制文件
每讀完規(guī)定byte數(shù)組大小的數(shù)據(jù)就寫入一次摄杂,最終不夠數(shù)組長度的的一次性寫入
FileInputStream fileInputStream = new FileInputStream("C:\\myPicture\\1.txt");
FileOutputStream fileOutputStream = new FileOutputStream("C:\\myPicture\\b.txt");
int read = 0;
byte[] b = new byte[1024];
while((read=fileInputStream.read(b))!=-1){
fileOutputStream.write(b);
}
fileInputStream.close();//關(guān)流
fileOutputStream.close();
二、字符流
字符輸入流Reader
上述程序中我們讀取擁有中文的文件時循榆,使用的字節(jié)流在讀取析恢,那么我們讀取到的都是一個一個字節(jié)。只要把這些字節(jié)去查閱對應(yīng)的編碼表秧饮,就能夠得到與之對應(yīng)的字符映挂。API中是否給我們已經(jīng)提供了讀取相應(yīng)字符的功能流對象,Reader盗尸,讀取字符流的抽象超類柑船。
read():讀取單個字符并返回
read(char[]):將數(shù)據(jù)讀取到數(shù)組中,并返回讀取的個數(shù)泼各。
FileReader類
發(fā)現(xiàn)FileInputStream用于讀取諸如圖像數(shù)據(jù)之類的原始字節(jié)流鞍时。要讀取字符流,請考慮使用FileReader扣蜻。
FileReader fileReader = new FileReader("C:\\myPicture\\1.txt");
int read = 0;
byte[] b = new byte[1024];
while ((read=fileReader.read())!=-1) {
System.out.println(read);
System.out.println((char)read);//能輸出中文了
}
fileReader.close();
輸出結(jié)果為每個字符對應(yīng)的數(shù)字和本身的值逆巍,中文也能輸出。
字符輸出流Writer 超類
FileWriter類是其子類
查閱FileOutputStream的API莽使,發(fā)現(xiàn)FileOutputStream用于寫入諸如圖像數(shù)據(jù)之類的原始字節(jié)的流锐极。要寫入字符流,請考慮使用FileWriter芳肌。
打開FileWriter的API介紹溪烤。用來寫入字符文件的便捷類味咳。此類的構(gòu)造方法假定默認字符編碼和默認字節(jié)緩沖區(qū)大小都是可接受的。
FileWriter fileWriter = new FileWriter("C:\\myPicture\\b.txt");
fileWriter.write("我們的愛情到這兒剛剛好");
fileWriter.flush();
fileWriter.close();
//此時b.txt里面已經(jīng)被寫入文字了
需要注意的是:
flush():將流中的緩沖區(qū)緩沖的數(shù)據(jù)刷新到目的地中檬嘀,刷新后槽驶,流還可以繼續(xù)使用。
close():關(guān)閉資源鸳兽,但在關(guān)閉前會將緩沖區(qū)中的數(shù)據(jù)先刷新到目的地掂铐,否則丟失數(shù)據(jù),然后在關(guān)閉流揍异。流不可以使用全陨。如果寫入數(shù)據(jù)多,一定要一邊寫一邊刷新衷掷,最后一次可以不刷新辱姨,由close完成刷新并關(guān)閉。
總結(jié):lIO流的分類
|-字節(jié)流
|-字節(jié)輸入流InputStream抽象類
|-FileInputStream操作文件的字節(jié)輸入流
|-字節(jié)輸出流OuputStream抽象類
|-FileOutputStream操作文件的字節(jié)輸出流
|-字符流
|-字符輸入流Reader抽象類
|- InputStreamReader輸入操作的轉(zhuǎn)換流
|- FileReader用來操作文件的字符輸入流(簡便的流)
|-字符輸出流Writer抽象類
|- OutputStreamWriter輸出操作的轉(zhuǎn)換流
|- FileWriter用來操作文件的字符輸出流(簡便的流)