文件輸入輸出流
文件輸入輸出流 FileInputStream 和 FileOutputStream 負(fù)責(zé)完成對本地磁盤文件的順序輸入輸出操作。
【例】通過程序創(chuàng)建一個文件,從鍵盤輸入字符,當(dāng)遇到字符“#”時結(jié)束,在屏幕上顯示該文件的所有內(nèi)容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import java.io.*; class ep10_5{ public static void main(String args[]){ char ch; int data; try { FileInputStream a= new FileInputStream(FileDescriptor.in); //創(chuàng)建文件輸入流對象 FileOutputStream b= new FileOutputStream( "ep10_5" ); //創(chuàng)建文件輸出流對象 System.out.println( "請輸入字符,以#號結(jié)束:" ); while ((ch=( char )a.read())!= '#' ){ b.write(ch); } a.close(); b.close(); System.out.println(); FileInputStream c= new FileInputStream( "ep10_5" ); FileOutputStream d= new FileOutputStream(FileDescriptor.out); while (c.available()> 0 ){ data=c.read(); d.write(data); } c.close();d.close(); } catch (FileNotFoundException e){ System.out.println( "找不到該文件!" ); } catch (IOException e){} } } |
FileDescriptor 是 java.io 中的一個類,該類不能實例化,其中包含三個靜態(tài)成員:in、out 和err,分別對應(yīng)于標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流和標(biāo)準(zhǔn)錯誤流,利用它們可以在標(biāo)準(zhǔn)輸入輸出流上建立文件輸入輸出流,實現(xiàn)鍵盤輸入或屏幕輸出操作。
【例】實現(xiàn)對二進(jìn)制圖形文件(.gif)的備份
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import java.io.*; class ep10_6{ public static void main(String args[]) throws IOException{ FileInputStream a= new FileInputStream( "ep10_6.gif" ); FileOutputStream b= new FileOutputStream( "ep10_6_a.gif" ); System.out.println( "文件的大小為:" +a.available()); byte c[]= new byte [a.available()]; a.read(c); //將圖形文件讀入數(shù)組 b.write(c); //將數(shù)組中的數(shù)據(jù)寫入到新文件中 System.out.println( "文件已經(jīng)被更名復(fù)制!" ); a.close(); b.close(); } } |
過濾流
FilterInputStream 和 FileOutputStream 是 InputStream 和 OutputStream 的直接子類,分別實現(xiàn)了在數(shù)據(jù)的讀、寫操作的同時能對所傳輸?shù)臄?shù)據(jù)做指定類型或格式的轉(zhuǎn)換,即可實現(xiàn)對二進(jìn)制字節(jié)數(shù)據(jù)的理解和編碼轉(zhuǎn)換。
常用的兩個過濾流是數(shù)據(jù)輸入流 DataInputStream 和數(shù)據(jù)輸出流 DataOutputStream。其構(gòu)造方法為:
1
2
|
DataInputStream(InputStream in); //創(chuàng)建新輸入流,從指定的輸入流 in 讀數(shù)據(jù) DataOutputStream(OutputStream out); //創(chuàng)建新輸出流,向指定的輸出流 out 寫數(shù)據(jù) |
由于 DataInputStream 和 DataOutputStream 分別實現(xiàn)了 DataInput 和 DataOutput 兩個接口(這兩個接口規(guī)定了基本類型數(shù)據(jù)的輸入輸出方法)中定義的獨立于具體機(jī)器的帶格式的讀寫操作,從而實現(xiàn)了對不同類型數(shù)據(jù)的讀寫。由構(gòu)造方法可以看出,輸入輸出流分別作為數(shù)據(jù)輸入輸出流的構(gòu)造方法參數(shù),即作為過濾流必須與相應(yīng)的數(shù)據(jù)流相連。
DataInputStream 和 DataOutputStream 類提供了很多個針對不同類型數(shù)據(jù)的讀寫方法,具體內(nèi)容讀者可參看 Java 的幫助文檔。
【例】將三個 int 型數(shù)字 100,0,-100 寫入數(shù)據(jù)文件 ep10_6.dat 中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.io.*; class ep10_7{ public static void main(String args[]){ String fileName= "ep10_7.dat" ; int value1= 100 ,value2= 0 ,value3=- 100 ; try { //將 DataOutputStream 與 FileOutputStream 連接輸出不同類型的數(shù)據(jù) DataOutputStream a= new DataOutputStream( new FileOutputStream(fileName)); a.writeInt(value1); a.writeInt(value2); a.writeInt(value3); a.close(); } catch (IOException i){ System.out.println( "出現(xiàn)錯誤!" +fileName); } } } |
運行后在程序目錄中生成數(shù)據(jù)文件 ep10_7.dat,用文本編輯器打開后發(fā)現(xiàn)內(nèi)容為二進(jìn)制的:
00 00 00 64 00 00 00 00 FF FF FF 9C。
【例】讀取數(shù)據(jù)文件 ep10_6.dat 中的三個 int 型數(shù)字,求和并顯示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.io.*; class ep10_8{ public static void main(String args[]){ String fileName= "D:\\myjava/ep10_7.dat" ; int sum= 0 ; try { DataInputStream a= new DataInputStream( new BufferedInputStream( new FileInputStream(fileName))); sum+=a.readInt(); sum+=a.readInt(); sum+=a.readInt(); System.out.println( "三個數(shù)的和為:" +sum); a.close(); } catch (IOException e){ System.out.println( "出現(xiàn)錯誤!" +fileName); } } } |
運行結(jié)果:
1
|
三個數(shù)的和為:0 |
readInt 方法可以從輸入輸出流中讀入 4 個字節(jié)并將其作為 int 型數(shù)據(jù)直接參與運算。由于已經(jīng)知道文件中有 3 個數(shù)據(jù),所以可以使用 3 個讀入語句,但若只知道文件中是 int 型數(shù)據(jù)而不知道數(shù)據(jù)的個數(shù)時該怎么辦呢?因為 DataInputStream 的讀入操作如遇到文件結(jié)尾就會拋出 EOFException 異常,所以可將讀操作放入 try 中。
1
2
3
4
5
6
7
8
|
try { while ( true ) sum+=a.readInt(); } catch (EOFException e){ System.out.pritnln( "三個數(shù)的和為:" +sum); a.close(); } |
EOFException 是 IOException 的子類,只有文件結(jié)束異常時才會被捕捉到,但如果沒有讀到文件結(jié)尾,在讀取過程中出現(xiàn)異常就屬于 IOException。
【例】從鍵盤輸入一個整數(shù),求該數(shù)的各位數(shù)字之和。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import java.io.*; class ep10_9{ public static void main(String args[]) throws IOException{ DataInputStream a= new DataInputStream(System.in); System.out.print( "請輸入一個整數(shù):" ); int b=a.readInt(); int sum= 0 ; int c=b; while (c> 0 ){ int d=c% 10 ; //取最低位 c=c/ 10 ; //去掉最低位 sum=sum+d; //累加各位之和 } System.out.println(b+ "的各位數(shù)字之和=" +sum); } } |
運行結(jié)果:
1
2
|
請輸入一個整數(shù):26 842403082 的各位數(shù)字之和=31 |
需要注意的是,輸入的數(shù)據(jù) 26 為變成了 842403082,原因在于輸入數(shù)據(jù)不符合基本類型數(shù)據(jù)的格式,從鍵盤提供的數(shù)據(jù)是字符的字節(jié)碼表示方式,若輸入 26,只代表 2 和 6 兩個字符的字節(jié)數(shù)據(jù),而不是代表整數(shù) 26 的字節(jié)碼。
若要從鍵盤得到整數(shù)需要先讀取字符串,再利用其他方法將字符串轉(zhuǎn)化為整數(shù)。
標(biāo)準(zhǔn)輸入輸出
System.in、System.out、System.err 這 3 個標(biāo)準(zhǔn)輸入輸流對象定義在 java.lang.System 包中,這 3 個對象在 Java 源程序編譯時會被自動加載。
標(biāo)準(zhǔn)輸入:標(biāo)準(zhǔn)輸入 System.in 是 BufferedInputStream 類的對象,當(dāng)程序需要從鍵盤上讀入數(shù)據(jù)時,只需要調(diào)用 System.in 的 read()方法即可,該方法從鍵盤緩沖區(qū)讀入一個字節(jié)的二進(jìn)制數(shù)據(jù),返回以此字節(jié)為低位字節(jié),高位字節(jié)為 0 的整型數(shù)據(jù)。
標(biāo)準(zhǔn)輸出:標(biāo)準(zhǔn)輸出 System.out 是打印輸出流 PrintStream 類的對象。PrintStream 類是過濾輸出流類 FilterOutputStream 的一個子類,其中定義了向屏幕輸出不同類型數(shù)據(jù)的方法print()和 println()。
標(biāo)準(zhǔn)錯誤輸出:System.err 用于為用戶顯示錯誤信息,也是由 PrintStream 類派生出來的錯誤流。Err 流的作用是使 print()和 println()將信息輸出到 err 流并顯示在屏幕上,以方便用戶使用和調(diào)試程序。
【例】輸入一串字符顯示出來,并顯示 System.in 和 System.out 所屬的類。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import java.io.*; class ep10_10{ public static void main(String args[]){ try { byte a[]= new byte [ 128 ]; //設(shè)置輸入緩沖區(qū) System.out.print( "請輸入字符串:" ); int count =System.in.read(a); //讀取標(biāo)準(zhǔn)輸入輸出流 System.out.println( "輸入的是:" ); for ( int i= 0 ;i<count;i++) System.out.print(a[i]+ "" ); //輸出數(shù)組元素的 ASCII 值 System.out.println(); for ( int i= 0 ;i<count- 2 ;i++) //不顯示回車和換行符 System.out.print(( char )a[i]+ "" ); //按字符方式輸出元素 System.out.println(); System.out.println( "輸入的字符個數(shù)為:" +count); Class InClass=System.in.getClass(); Class OutClass=System.out.getClass(); System.out.println( "in 所在的類為:" +InClass.toString()); System.out.println( "out 所在的類為:" +OutClass.toString()); } catch (IOException e){} } } |
運行結(jié)果如所示:
需要注意的是,輸入了 3 個字符按回車后,輸出的結(jié)果顯示為 5 個字符。這是由于 Java 中回車被當(dāng)作兩個字符,一個是 ASCⅡ為 13 的回車符,一個是值為 10 的換行符。程序中 getClass()和 ToString()是 Object 類的方法,作用分別是返回當(dāng)前對象所對應(yīng)的類和返回當(dāng)前對象的字符串表示。