9.1?Java輸入輸出流 所有的程序語言都提供與本機文件系統交互的方式,Java也不例外。我們將看看Java是怎樣處理標準文件輸入輸出的(包括stdin,stout,stderr)。當你在網絡上開發小程序時,你必須注意直接文件輸入輸出是不安全因素的關鍵。大多數用戶設置他們的瀏覽器,可讓你自由的訪問他們的文件系統,但有些不讓你訪問。當然,如果你開發你內部的應用程序,你也許需要直接訪問文件。 標準輸入輸出Unix的用戶,或其他基于命令行系統的用戶(如DOS),都知道標準輸入輸出的含義。標準輸入文件是鍵盤,標準輸出文件是你的終端屏幕。標準錯誤輸出文件也指向屏幕,如果有必要,它也可以指向另一個文件以便和正常輸出區分。系統類Java通過系統類達到訪問標準輸入輸出的功能。 上面提到的三個文件在這個系統類中實現:Stdin?System.in作為InputStream類的一個實例來實現stdin,你可以使用read()和skip(long?n)兩個成員函數。read()讓你從輸入中讀一個字節,skip(long?n)讓你在輸入中跳過n個字節。Stout?System.out作為PrintStream來實現stdout,你可以使用print()和println()兩個成員函數。這兩個函數支持Java的任意基本類為參數。Stderr?System.err同stdout一樣實現stderr。象System.out一樣,你可以訪問PrintStream成員函數。 9.2?標準輸入輸出例子 這里有一個例子,功能象Unix里的cat或type: import?java.io.* class?myCat{ public?void?main(String?args[]) throws?IOException{ int?b; int?count?=?0; while?((b?=?System.in.read())?!=?-1){ count++; System.out.print((char)b); } System.out.println();?//blank?line System.err.println("counted"+count+"total?bytes."); } } 9.3?普通輸入輸出類 除了基本的鍵盤輸入和屏幕輸出外,我們還需要聯系文件的輸入輸出。我們將學習下面幾個類: FileInputStream DataInputStream FileOutputStream DataOutputStream 作為參考,再列出一些特定應用的類: PipedInputStream BufferedInputStream PushBackInputStream StreamTokenizer PipedOutputStream BufferedOutputStream RandomAccessFile 我們不在此討論這些類,但你可以在JAVA_HOME/src/java/io目錄里查看每個類的成員函數定義。 9.4?文件 在我們進行文件操作時,需要知道一些關于文件的信息。File類提供了一些成員函數來操縱文件和獲得一些文件的信息。 9.4.1?創建一個新的文件對象 你可用下面三個方法來創建一個新文件對象: File?myFile;?myFile?=?new?File("etc/motd"); myFile?=?new?File("/etc","motd");?//more?useful?if?the?directory?or?filename?are?variables File?myDir?=?new?file("/etc");?myFile?=?new?File(myDir,"motd"); 這三種方法取決于你訪問文件的方式。 例如,如果你在應用程序里只用一個文件,第一種創建文件的結構是最容易的。但如果你在同一目錄里打開數個文件,則第二種或第三種結構更好一些。 9.4.2?文件測試和使用 一旦你創建了一個文件對象,你便可以使用以下成員函數來獲得文件相關信息: 文件名 String?getName()、String?getPath()、String?getAbslutePath()、String?getParent()、boolean?renameTo(File?newName) 文件測試 boolean?exists()、boolean?canWrite()、boolean?canRead()、boolean?isFile()、boolean?isDirectory()、boolean?isAbsolute() 一般文件信息 long?lastModified()、long?length() 目錄用法 boolean?mkdir()、String[]?list() 9.4.3?文件信息獲取例子程序 這里是一個獨立的顯示文件的基本信息的程序,文件通過命令行參數傳輸: import?java.io.*; class?fileInfo{ File?fileToCheck; public?static?void?main(String?args[]) throws?IOException{ if?(args.length>0){ for?(int?i=0;i<args.length;i++){ fileToCheck?=?new?File(args[i]); info(fileToCheck); } }else{ System.out.println("No?file?given."); } } public?void?info?(File?f) throws?IOException?{ System.out.println("Name:?"+f.getName()); System.out.println("Path:?"=f.getPath()); if?(f.exists())?{ System.out.println("File?exists."); System.out.print((f.canRead()??"?and?is?Readable":"")); System.out.print((f.cnaWrite()?"?and?is?Writeable":"")); System.out.println("."); System.out.println("File?is?"?+?f.lenght()?=?"?bytes."); }else{ System.out.println("File?does?not?exist."); } } } 9.5?輸入流 ?InputStream?SequenceInputStream?FileInputStream?PipedInputStream?ByteArrayInputStream?FileterInputStream?StringBufferInputStream?DataInputStream?LineNumberInputStream?PushbackInputStream?BufferedInputStream?有好幾個類是專門用來處理文件輸入的。 下面是文件輸入類的層次結構: 9.5.1?FileInputStream對象 FileInputStream典型地表示一種順序訪問的文本文件。通過使用FileInputStream你可以訪問文件的一個字節、幾個字節或整個文件。 9.5.2?打開FileInputStream 為一個文件打開輸入流FileInputStream,你必須將文件名或文件對象傳送給結構: FileInput?Stream?myFileStream; myFileStream?=?new?FileInputStream?(?"/etc/motd"); 你還可以象下邊這樣從FileInputStream里讀文件信息: File?myFile; FileInputSteam?myFileStream; myFile?=?new?File("/etc/motd"); myFileStream?=?new?FileInputStream(myFile); 一旦FileInputStream輸入流打開,你就可以從里面讀取信息了。read()成員函數有以下幾種選項: int?read()?//reads?one?byte?//return?-1?at?end?of?stream int?read(byte?b[])?//fills?entire?array,if?possible?//returns?number?of?bytes?read?//returns?-1?if?end?of?stream?is?reached int?read(byte?b[],int?offset,?int?len)?//reads?len?bytes?into?b?starting?at?b[offset]?//Returns?number?of?bytes?read,?//or?-1?if?end?of?stream?is?reached. 9.5.3關閉FileInputStream 當你完成一個文件的操作,你可選兩種方法關閉它:顯式關閉和隱式關閉。隱式關閉是自動垃圾回收時的功能,顯式關閉如下:?myFileStream.close();。 9.6?例?程:顯示一個文件 如果文件的訪問權限足夠,你可以在TextArea對象里顯示文件內容。下面是顯示文件的程序片斷: FileInputStream?fis; TextArea?ta; public?vod?init(){ byte?b[]?=?new?byte?[1024]; int?I;?//make?it?big?enough?or?wait?until?you?//know?the?size?of?the?file?String?s; try?{ fis?=?new?FileInputStream("/etc/motd"); }catch(FileNotFoundException?e){ /*do?something?appropriate?*/ } try?{ I=?fis.read(b); }catch(IOException?e){ ?/*?do?something?appropriate?*/ } s?=?new?String(b,?0); ta?=?new?TextArea(s,5,40); add?(ta); } 9.7?DataInputStreams DataInputStreams與FileInputStreams差不多。Data流可以直接讀任意一種變量類型,如浮點數,整數和字符等。一般來說,對二進制文件使用DataInputStream流。 9.7.1?打開和關閉DataInputStreams 打開和關閉DataInputStreams對象時,其方法與FileInputStreams相同: DataInputStreams?myDataStream; FileInputStreams?myFileStream;?//get?a?file?handle myFileStream?=?new?FileInputStream("/usr/db/stock.dbf");?//open,or?"chain"?a?data?input?file myDataStream?=?new?DataOutputStream(myFileStream);?//Now?we?can?use?both?input?streams?to?access?our?file?//j(If?we?want?to...) myFileStream.read(b); I?=?myDataStrea.readInt();?//close?the?data?friel?explicityly?//Always?close?the?"topmost"?file?stream myDataStream.close(); myFileStream.close(); 9.7.2?讀DataInputStreams 當你從DataInputStreams流里訪問文件時,你可以使用與FileInputStream流相同的成員函數read()。但你也可以使用其他訪問方法來讀取不同種類的數據:byte?readByte()、int?readUnsignedByte()、short?readShort()、int?readUnsighedShort()、char?readChar()、int?readInt、long?readLong()、float?readFloat()、double?readDouble()、String?readLine() 以上每一個成員函數都讀取相應的數據對象。象String?readLine()成員函數,你可使用\n,\r,\r\n,或EOF作為字符串結束符。讀一個長整型,例如:long?serialNo;?...?serialNo?=?myDataStream.readLong(); 9.8?URL輸入流 除了基本文件訪問外,Java還提供了通過網絡使用URL訪問對象的功能。在下面這個例子里,我們用getDocumentBase()成員函數并顯式指定URL對象來訪問聲音和圖象。 String?imageFile?=?new?String?("images/Duke/T1.gif"); images[0]?=?getImage(getDocumentBase(),imageFile(); 如果我們愿意,可以直接使用URL: URL?imageSource; imageSource?=?new?URL("http://555-1212.com/~info"); images[0]?=?getImage(imageSource,"Duke/T1.gif"); 我們可以為相應的URL打開輸入流。例如,下面的程序里包括一個數據文件: InputStream?is; byte?buffer[]?=?new?byte[24]; is?=?new?URL(getDocumentBase(),dataname).openStream(); 現在我們可以使用is,就象使用FileInputStream對象一樣:is.read(buffer.0,buffer.length); 注意:有些用戶設置了他們的瀏覽器安全屬性,可以不讓你的程序訪問他們的文件。 9.9?OutputStreams 上面我們談到了讀數據,那么如何實現寫數據呢?象輸入流一樣,輸出流也有類似的層次結構:OutputStream?FileOutputStream?PipedOutputStream?ByteArrayOutputStream?FilterOutputStream?DataOutputStream?PrintStream?BufferedOutputStream?我們將分析FileOutputStream和DataOutputStream類來完成我們碰到的輸出流問題。其它的輸出流包含了更多的信息和成員函數。象輸入流的源文件一樣,這些文件在$JAVA_HOME/src/java/io目錄下。 9.9.1?FileOutputStream類 FileOutputStream對象用于向一個文本文件寫數據。象輸入文件一樣,你得先打開這個文件后才能寫這個文件。 9.9.2?打開一個FileOutputStream對象 要打開一個FileOutputStream對象,象打開一個輸入流一樣,你可以將字符串或文件對象作為參數: FileOutputStream?myFileStream; myFileStream?=?new?FileOutputStream("/etc/motd"); 象輸入流一樣,你也可這樣使用: File?myFile; FileOutputStream?myFileStream; myFile?=?new?File("/etc/motd"); myFileStream?=?new?FileOutputStream(myFile); 9.9.3?寫入一個流 一旦文件被打開,你便可以使用write()函數向文件里寫一些數據。就象輸入流的read()函數一樣,你可有三種方法: void?write(int?b);//writes?out?one?byte void?write(byte?b[]);//writes?out?entire?array void?write?(byte?b[],int?offset,int?length);//write?out?length?bytes?of?b[],starting?at?b[offset] 9.9.4?關閉一個FileOutputStream對象 關閉輸出流和關閉輸入流方法一樣,你可以使用顯式方法:myFileStream.close();你也可以讓系統自動關閉它。 9.10?例子:存儲信息 下面有一個程序,讓用戶輸入一些姓名和電話號碼。每一個姓名和號碼將加在文件里。用戶通過點“Done"按鈕來告訴系統整個列表已輸入完畢。一旦用戶輸入完整個列表,程序將創建一個輸出文件并顯示或打印出來。例如: 555-1212,Tom?123-456-7890,Peggy?L.?234-5678,Marc?234-5678,Ron?876-4321,Beth&Brian?33.1.42.45.70,Jean-Marc 下面是程序的源代碼: import?java.io.*;?//Phones.java?//A?simple?database?creation?program class?Phones{ static?FileOutputStream?fos; public?static?final?int?lineLength?=?81; public?static?void?main(String?args[]) throws?IOExciption?{ byte[]?phone?=?new?byte[lineLength]; byte[]?name?=?new?byte[lineLenght]; int?I; fos?=?new?FileOutputStream("phone.numbers"); while?(true){ System.err.println("Enter?a?name?(enter?’done’?to?quit)"); readLine(name); if?("done".equalsIgnoreCase(new?String(name,0,0,4))){ break; } System.err.println("Enter?the?phone?number"); readLine(phone); for?(?i=0;phone[i]!=?0;i++)?{ fos.write(phone[i]); } fos.write(’,’); for?(i=0;name[i]!=?0;I++)?{ fos.write(name[i]); } fos.write(’\n’); } fos.close(); } private?static?void?readLine(byte?line[]) throws?IOException?{ int?i=0,b=0; while?((i<lineLengh-1))&&((b=System.ini.read())!=’\n’)){ line[i++]?=?(byte)b; } line[i]=(byte)?0; } } 9.11?BufferedOutput流 如果你處理的數據量很多,或向文件寫很多次小數據,你可以使用一個BufferedOutput流。BufferedOutput流提供和FileOutputStream類同樣的寫操作方法,但所有輸出全部存放在一個緩沖區里。當你填滿緩沖區,它將一次性寫入磁盤?;蛘吣阒鲃訉⒕彌_區寫入磁盤。 9.11.1?創建BufferedOutput流 如果要創建一個BufferedOutput流,首先需要一個FileOutput流。然后將緩沖區鏈接到FileOutput流: FileOutputStream?myFileStream; BufferedOutputStream?myBufferStream;?//get?a?file?handle myFileStream?=?new?FileOutputStream("/usr/db/stock.dbf");?//chain?a?buffered?output?stream myBufferSSstream?=?new?BufferedOutputStream(myFileStream); 9.11.2?更新和關閉BufferedOutput流 和普通FileOutput流一樣,向BufferedOutput流里的每一次寫操作和寫入磁盤操作并不是一一對應的。要想在程序結束之前將緩沖區里的數據寫入磁盤,除非填滿緩沖區,否則只有顯式調用flush()函數: //force?left-over?data?to?disk myBufferStream.flush(); //close?the?data?file?explicitly myBufferStream.close(); //Always?close?the?"topmost"?file?stream myFileStream.close(); 9.12?DataOutput流 和DataInputStream對應,Java還提供了DataOutput流。使用DataOutput流,我們可以向文件寫入二進制數據。 9.12.1?打開和關閉DataOutput流對象 打開和關閉DataOutput流對象與打開、關閉FileOutput流對象方法一樣: DataOutputStream?myDataStream; FileOutputStream?myFileStream; BufferedOutputStream?myBufferStream;?//get?a?file?handle mhyFileStream?=?new?FileOutputStream("/usr/db/stock.dbf");?//chain?a?buffered?output?stream?(for?efficiency); myBufferStream?=?new?BufferedOutputStream(myFileStream);?//chain?a?data?output?file myDataStream?=?new?DataOutputStream(myBufferStream);?//Now?we?can?use?both?input?streams?to?access?our?file?//(iiIf?we?want?to?...) myBufferStream.write(b); myDataStream.writeInt(i);?//close?the?data?file?explicitly?//Always?colse?the?"topmost"?file?stream? myDataStream.close(); myBuffersStream.close(); myFileStream.close(); 9.12.2?向DataOutput流寫數據 FileOutput流里的write()函數各種方法都適用于DataOutput流。你還可以看到DataInput流的類似函數方法: void?writeBoolean?(boolean?v) void?writeByte?(int?v) void?writeShort?(int?v) void?writeChar?(int?v) void?writeInt?(int?v) void?writeFloat?(float?v) void?writeDouble?(double?v) void?writeBytes?(string?s) void?writeChars?(string?s) 對字符串來說,有兩種選擇:byte和char。記住byte是8位數據而char是16位數據。如果你想利用Unicode字符的優點,你應使用writeChars()函數。 9.12.3?輸出記數 在使用二進制數據輸出時常用的另外一個函數是size()。這個函數返回寫入文件數據的總字節數。你也可用size()函數將數據文件分成四字節為單位的塊,例如: ... int?bytesLeft?=?myDataStream.size()%4; for?(int?I?=?0;?I<?bytesLeft;?I++)?{ myDataStrea.write(0); } ... 9.13?隨機訪問文件 我們讀文件常常不是從頭至尾順序讀的。你也許想將一文本文件當作一個數據庫,讀完一個記錄后,跳到另一個記錄,它們在文件的不同地方。Java提供了RandomAccessFile類讓你操作這種類型的輸入輸出。 9.13.1?創建隨機訪問文件 打開隨機訪問文件有兩種方法: 用文件名?myRAFile?=?new?RandomAccessFile(String?name,String?mode); 用文件對象?myRAFile?=?new?RandomAccessFile(File?file,String?mode); mode參數決定了訪問文件的權限,如只讀’r’或讀寫’wr’等。例如,我們打開一個數據庫更新數據: RandomAccessFile?myRAFile; myRAFile?=?new?RandomAccessFile("/usr/db/stock.dbf","rw"); 9.13.2?訪問信息 RandomAccessFile對象的讀寫操作和DataInput/DataOutput對象的操作方式一樣。你可以使用在DataInputStream和DataOutputStream里出現的所有read()和write()函數。還有幾個函數幫助你在文件里移動指針: long?getFilePointer();?返回當前指針 void?seek(long?pos);?將文件指針定位到一個絕對地址。地址是相對于文件頭的偏移量。地址0表示文件的開頭。 long?length();?返回文件的長度。地址"length()"表示文件的結尾。 9.13.3?增加信息 你可以使用隨機訪問文件來設置成增加信息模式: myRAFile?=?new?RandomAccessFile("/tmp/java.log","rw"); myRAFile.seek(myRAFile.length());?//Any?subsequent?write()s?will?be?appended?to?the?file 9.13.4?追加信息例子 下面是一個在已存在文件后面追加字符串的例子: import?java.io.IOException; import?java.io.RandomAccessFile; class?raTest?{ public?static?void?main(String?args[]) throws?IOException?{ RandomAccessFile?myFAFile; String?s?=?"Information?to?Append\nHi?mom!\n";?//open?our?random?access?file myRAFile?=?new?RandomAccessFile("/tmp/java.log","rw");?//move?to?the?end?of?the?file? myRAFile.seek(myRAFile.length());?//Start?appending! myRAFile.writeBytes(s); myRAFile.close(); } } 本章小結 1.?Java通過系統類達到訪問標準輸入輸出的功能。 2.?你可以創建、讀、寫文件。
來自:http://www.linux8.net/html/java/2005-11/16/21_38_02_170.html
|
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
26 | 27 | 28 | 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 | 30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
導航
統計
- 隨筆: 115
- 文章: 1
- 評論: 86
- 引用: 0
常用鏈接
留言簿(5)
隨筆檔案(115)
網址
搜索
積分與排名
最新評論

閱讀排行榜
評論排行榜
|
|