分类: Java
2008-11-23 10:15:08
java.io套裝模組提供相當多的類別(classes)供程式設計師解決各種I/O的問題。甚至在網際網路盛行之後,更以Unicode編碼做為Java編碼的標準,因為跨平台、多國語言處理能力也成為Java的重要特性之一。
資料I/O與通訊的新需求不斷浮現,程式庫中的類別也隨之改變。JDK 1.0版程式庫中的類別原以Byte為主,在JDK 1.1版之後增添了許多以char和Unicode為主的類別。這起因於網際網路盛行後,為了讓資料的來源端與目的端能互相跨越地順暢通訊,Unicode的編碼方式便成為Java編碼的標準,也因著這項特性Java程式才能順利地在不同平台(Windows、Unix或Linux)上撰寫與執行。
Java I/O(輸入/輸出)
程式設計師藉由輸入/輸出(I/O)可在程式執行的過程中存取外部資料(包含檔案、記憶體、網路連結Socket或Console等),且允許有不同的來源端(Source)與目的端(Sink)。
撰寫一個好的I/O系統程式並不容易,所涉及的技術與知識不只是程式本身,還要考慮資料來源端與目的端的設備與通訊是否完備;各種例外狀況的發生也讓程式設計師在開發時感到頭痛,除了程式的例外處理,還必須對整體系統架構或網路系統做全盤了解。幸好java.io類別提供了許多函式庫,為程式設計師節省了程式開發的時間,使資料I/O能順暢地進行。
File類別(non-stream)
File類別並不是一個標準的I/O類別,在java.io類別函式中它是唯一的non-stream類別,既不能讀取檔案內容,也不能改變檔案內容,主要作用是收集檔案(或目錄)的相關資訊,例如:建立檔案、修改檔名、設定檔案屬性、測試或檢查檔案、建立目錄、顯示某目錄中一組的檔案名稱等…。
● File建構子
|
File類別包含在java.io.File套件中,在程式中使用File類別時,必須先以import關鍵字載入相對的套件路徑:import java.io.File或java.io.*。利用File()產生檔案實體並指定某個目錄時,該目錄下所有的檔案將以陣列方式傳回(array of files)。
File常用方法:建立檔案、目錄的方法
|
1. import java.io.*; 2. public class IO_File 3. { 4. public static void main(String[] args) 5. { 6. File f = new File("tmp", "NewFile.txt"); 7. System.out.println("檔案是否存在?" + f.exists()); 8. try 9. { 10. if (!f.exists()) 11. { 12. System.out.println("利用createNewFile()建立新檔案,是否建立成功?" + 13. f.createNewFile()); 14. System.out.println("檢查新建檔案是否存在於檔案系統中?" + f.exists()); 15. } 16. } 17. catch(Exception e){} 18. } 19. } | |
執行結果: 檔案是否存在?false 利用createNewFile()建立新檔案,是否建立成功?true檢查新建檔案是否存在於檔案系統中?true |
程式第6行建立File類別物件實體並指派給f物件變數,f是目前所在目錄下tmp子目錄中的NewFile.txt。第7行利用exists()方法來判斷f物件變數所指的檔案或目錄是否存在於實體檔案系統。第10行判斷檔案不存在後,第13行利用createNewFile()方法建立新檔NewFile.txt,第14行再利用exists()方法來判斷所產生出來的檔案是否已經建立在實體檔案系統中。
修改檔案、路徑的方法
方法名稱 |
傳回值 |
說明 |
renameTo(File dest) |
boolean |
修改檔名或目錄路徑。 |
刪除檔案、路徑的方法
方法名稱 |
傳回值 |
說明 |
delete() |
boolean |
刪除指定的檔名或目錄路徑 |
deleteOnExit() |
void |
在程式結束時(when the virtual machine terminates)刪除指定的檔名或目錄路徑。 |
存取檔案、路徑屬性的方法
方法名稱 |
傳回值 |
說明 |
exists() |
boolean |
判斷檔案或目錄是否存在 |
isAbsolute() |
boolean |
判斷是否為絕對路徑 |
isDirectory() | boolean | 判斷是否為目錄 |
isFile() | boolean | 判斷是否為檔案 |
isHidden() | boolean | 判斷檔案是否為隱藏檔 |
canRead() | boolean | 判斷檔案是否可讀取 |
canWrite() | boolean | 判斷檔案是否可寫入 |
存取檔案、路徑內容的方法(非檔案內的實體資料)
方法名稱 |
傳回值 |
說明 |
getName() |
String |
取得檔案名稱 |
getAbsoluteFile() |
File |
取得絕對路徑 |
getAbsolutePath() | String | 取得絕對路徑 |
getPath() | String | 取得路徑 |
getParent() | String | 取得上層路徑,入傳回值為null則表示沒有所指定的上層路徑名稱。 |
length() | long | 取得檔案大小(bytes),此方法只對檔案有有若是目錄的話則回傳值是0。 |
list() | String[] | 傳回指定目錄下所有的檔案或目錄 |
listFiles() | File[] | 只傳回指定目錄下所有的檔案 |
lastModified() | long | 取的檔案最後的修改時間(以微秒為單位) |
1. import java.io.*; 2. public class IO_FileList 3. { 4. public static void main(String[] args) 5. { 6. File f = new File("D:/prg/SCJP/tmp/"); 7. String[] FL = f.list(); 8. int i; 9. for(i=0;i 10. { 11. File fn = new File("D:/prg/SCJP/tmp/" + FL[i]); 12. System.out.print(FL[i]); 13. if (fn.isDirectory()) 14. System.out.println(":is Directory(目錄)."); 15. else 16. System.out.println(":is File(檔案)."); 17. } 18. } 19. } | |
|
程式第6行將File指定到某個特定目錄(D:/prg/SCJP/tmp/)。請注意!目錄間是除號(”/”)而非反斜線(”\”)。第7行宣告一個字串陣列變數FL來接收f.list()所傳回的資料。第9~17行利用for-loop將每一個陣列元素取出,每一個陣列元素都可能是一個File或Directory。第11行根據所取得的陣列元素內容加上原始路徑再次建立File物件並指派給fn物件變數。第13~16行利用isDirectory()方法來區別fn物件變數所指向的是File還是Directory,若傳回值為true表示是Directory;傳回值為false則是File。此外,也可改成用isFile()方法來判別(true值表示File;false值則為Directory。
Filenamefilter(檔名過濾器)通常一個目錄之下會包含著不同類型的檔案,例如*.doc、*.html、*.txt、*.java…等,檔案類型是以副檔名來區分。在這麼多檔案中,若只取JAVA原始碼檔,且知道其副檔名是”.java”(即*.java),利用Filenamefilter(檔名過濾器)則可過濾其它檔名,只顯示副檔名為.java(*.java)的檔案。Filenamefilter是一個介面(interface),使用前必須先建立一個能實作出Filenamefilter介面的類別,Filenamefilter介面包含了一個accept()方法,如下所示。
方法名稱 |
傳回值 |
說明 |
accept(File dir, String name) |
boolean |
所指定的檔案是否被包含在檔案列表中 dir:某個特定檔案的所在目錄;name:檔案名稱 |
Console主控台 I/O
Java提供了3種標準I/O模式分別是:
1. System.in:標準輸入裝置(standard input)是一個InputStream物件,但System.in不可單獨使用,必須內含於某個InputStream物件中。
2. System.out:標準輸出裝置(standard output)是一個可以單獨使用的PrintStream物件。
3. System.err:標準顯示錯誤裝置(standard error)也是一個可以單獨使用的PrintStream物件。
【圖1】Java I/O介面輸出輸入關係圖 |
System.in預設資料來源裝置是鍵盤(Keybord),System.out與System.err皆屬於PrintStream物件,其預設的輸出裝置是螢幕(print to terminal window)。
【圖2】Java I/O類別物件運作關係圖 |
PrintStream建構子
PrintStream建構子 |
說明 |
PrintStream(OutputStream out) |
建立一個新的PrintStream物件 |
PrintStream(OutputStream out, boolean autoFlush) |
建立一個新的PrintStream物件並設定緩衝區的資料是否先自動清除,若autoFlush設為true,表示要將緩衝區內的資料自動清除。 |
PrintStream(OutputStream out, boolean autoFlush, String encoding) | 建立一個新的PrintStream物件,並設定緩衝區資料是否自動清除,以及為輸出資料編碼(encoding)。 |
更改輸出與輸入介面
利用System.setIn、System.setOut與Syste.setErr可更改輸出與輸入介面。若想將所輸出的結果寫入檔案中而非輸出到螢幕上,可利用System.setOut來變更輸出裝置(System.out預設的輸出裝置是螢幕)。
1. import java.io.*; 2. public class Ex_SystemSetOut 3. { 4. public static void main(String[] args) throws IOException 5. { 6. InputStreamReader in = new InputStreamReader(System.in); 7. BufferedReader buf_in = new BufferedReader(in); 8. FileOutputStream fo = new FileOutputStream("setOut.txt"); 9. BufferedOutputStream buf_out = new BufferedOutputStream(fo); 10. PrintStream out = new PrintStream(buf_out, true); 11. System.setOut(out); 12. String s; 13. while((s = buf_in.readLine()).length() != 0) 14. { 15. if (s == "exit") System.exit(0); 16. out.println("Get user input --> " + s); 17. } 18. out.flush(); //將緩衝區內容清出 19. out.close(); //關閉Stream(記得要加) 20. } 21. } | |
執行結果: Setp4:利用記事本打開setOut.txt檔,我們可以看到先前我們在程式執行中所輸入的資料。 |
更改I/O介面是用Stream來處理,因此程式中第8、9、10行必須使用FileOutputStream、BufferedOutputStream 與 PrintStream 類別來作檔案的輸出處理。第11行利用 System.setout() 方法更改輸出裝置,將輸出裝置從原本的螢幕輸出更改為檔案輸出(將使用者輸入的資料寫入setOut.txt中)。第18行利用flush()方法將緩衝區內容清出,在第19行請關閉Stream(close stream)。