440 likes | 628 Views
Ch08 基本輸出入與檔案處理. 物件導向系統實務. 大綱. Java 的輸入 / 輸出串流 檔案與資料夾處理 標準輸出與輸入串流 Reader/Writer 檔案串流 InputStream/OutputStream 檔案串流 隨機存取檔案的處理. Java 的輸入 / 輸出串流. Java I/O 套件的全名是 Java Input/Output (輸入 / 輸出),即應用程式的資料輸入與輸出,在 Java 類別函式庫( Class Library )是使用「串流」( Stream )模型來處理資料的輸入與輸出。. 串流的基礎.
E N D
Ch08 基本輸出入與檔案處理 物件導向系統實務
大綱 • Java的輸入/輸出串流 • 檔案與資料夾處理 • 標準輸出與輸入串流 • Reader/Writer檔案串流 • InputStream/OutputStream檔案串流 • 隨機存取檔案的處理
Java的輸入/輸出串流 • Java I/O套件的全名是Java Input/Output(輸入/輸出),即應用程式的資料輸入與輸出,在Java類別函式庫(Class Library)是使用「串流」(Stream)模型來處理資料的輸入與輸出。
串流的基礎 • 串流(Stream)觀念最早使用在Unix作業系統,串流模型如同水管的水流,當程式開啟一個來源的輸入串流(例如:檔案、記憶體和緩衝區等),Java程式可以從輸入串流依序讀取資料,如下圖所示:
java.io套件的串流類別-說明 • Java的java.io套件提供多種串流類別,基本上,Java串流類別分成兩大類: • 「字元串流」(Character Stream) • 「位元組串流」(Byte Stream)
java.io套件的串流類別-字元串流 字元串流(Character Stream) • 字元串流是Java 1.1版才支援的串流類別,這是一種適合「人類閱讀」(Human-readable)的串流,Reader/Writer兩個類別分別讀取和寫入16位元的字元資料,屬於字元串流的父抽象類別。
java.io套件的串流類別-位元組串流 位元組串流(Byte Stream) • 位元組串流是一種「電腦格式」(Machine-formatted)串流,可以讀取和寫入8位元的位元組資料,也就是處理二進位資料的執行檔、圖檔和聲音等,其父抽象類別的輸入/輸出串流名稱為InputStream/OutputStream類別。
檔案與資料夾處理 • 在真正進入本章主題輸出入和檔案處理前,筆者準備先說明java.io套件的File類別。 • File類別可以處理作業系統的檔案和資料夾,讓Java程式取得指定資料夾的檔案和子資料夾清單、檔案資訊、建立資料夾和刪除檔案等操作。
顯示檔案和資料夾清單-建立File物件 • 在Java程式只需建立File物件,就可以取得檔案或資料夾的相關資訊,如下所示: File f = new File(String); • 上述程式碼建立File物件,File()建構子參數是檔案或資料夾路徑。
顯示檔案和資料夾清單-取得檔案與資料夾清單顯示檔案和資料夾清單-取得檔案與資料夾清單 • 如果是資料夾,可以進一步使用下列方法取得檔案和資料夾清單,如下表所示:
顯示檔案資訊 • 在File類別提供方法取得檔案相關資訊,如下:
更改檔案名稱 • File類別提供方法更改檔案或資料夾名稱,其方法如下表所示:
刪除檔案 • File類別提供方法可以刪除檔案或資料夾,其方法如下表所示:
建立資料夾 • File類別提供方法可以建立子資料夾,其方法如下表所示:
瀏覽檔案與資料夾視窗-說明 • 現在我們已經能夠在Java程式使用File物件處理檔案和資料夾,接下來的程式範例是使用File物件和Swing套件建立瀏覽檔案與資料夾視窗。 • 本節的Java程式並不是使用Swing套件的JList元件,而是使用AWT的List類別儲存File物件list()方法取得的檔案和資料夾清單,如下所示: List lstItems = new List(elementCount); • 上述程式碼建立List物件lstItems,參數elementCount是顯示的項目數。
標準輸出與輸入串流-說明 • Java語言的標準輸出和輸入是指System類別的System.out和System.in子類別,不過,System類別並不是屬於java.io套件,而是屬於java.lang套件。 • 在本章之前的Java程式範例早已經大量使用System.out的println()和print()方法輸出資料,如下所示: System.out.println("…."); System.out.print("….");
標準輸出與輸入串流-方法 • Reader/Writer父類別提供一些方法,可以在串流讀取和寫入字元和字元陣列,如下表所示:
標準輸出-說明 • 在Java程式將字串輸出到螢幕顯示就是開啟System.out標準輸出的OutputStreamWriter串流,我們可以使用緩衝器類別的BufferedWriter串流加速資料處理,如下所示: BufferedWriter output = new BufferedWriter(new OutputStreamWriter(System.out));
標準輸出-方法 • BufferedWriter類別是繼承自Writer類別且新增過載方法write()輸出字串內容,如下表所示:
範例1:標準輸出範例 • import java.io.*; • // 主類別 • public class Ch10_05 • { // 主程式 • public static void main(String[] args) • throws Exception • { // 建立BufferedWriter的輸出串流物件 • BufferedWriter output = new BufferedWriter( • new OutputStreamWriter(System.out)); • String str = "Java 2程式設計範例教本2e"; • output.write(str); // 輸出字串 • output.close(); // 關閉串流 • } • }
標準輸入-說明 • Java程式從鍵盤輸入資料是開啟System.in標準輸出的InputStreamReader串流,同樣可以使用緩衝器類別BufferedReader串流加速資料處理,如下所示: BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
標準輸入-方法 • BufferedReader類別是繼承自Reader類別,新增方法readLine(),如下表所示:
範例2:使用標準輸入 • import java.io.*; • // 主類別 • public class Ch10_06 • { // 主程式 • public static void main(String[] args) • throws Exception • { // 建立BufferedReader的輸入串流物件 • BufferedReader input = new BufferedReader( • new InputStreamReader(System.in)); • String str; • System.out.print("請輸入資料: "); • System.out.flush(); // 清除緩衝區 • str = input.readLine(); // 讀取一列 • input.close(); // 關閉串流 • System.out.println("輸入的資料是: " + str); • } • }
寫入文字檔案 • 當目標串流是一個檔案,在Java程式可以開啟檔案的FileWriter串流,然後使用緩衝器BufferedWriter串流來加速資料處理,如下所示: BufferedWriter output = new BufferedWriter(new FileWriter(file)); • 上述程式碼的參數file是檔案路徑字串,在開啟後,就可以使用write()方法將字串寫入檔案。
讀取文字檔案 • Java程式可以開啟檔案的FileReader串流來讀取檔案內容,同樣可以使用緩衝器BufferedReader串流來加速資料處理,如下所示: BufferedReader input = new BufferedReader(new FileReader(name)); • 上述程式碼的參數name是File物件,然後就可以使用while迴圈讀取檔案內容,如下所示: while ( (str = input.readLine()) != null ) { …… }
檔案複製 • Java程式只需整合第14-4-1節和第14-4-2節的程式範例,就可以建立檔案複製程式,首先使用FileReader和FileWriter串流分別開啟來源和目的檔案串流,複製部分是一個while迴圈,如下所示: while ( (ch = input.read()) != -1 ) output.write(ch); • 上述程式碼使用read()方法讀取整數,然後使用write()方法寫入目的檔案。
範例3:複製檔案=讀取檔案+寫入文字檔案 • import java.io.*; • // 主類別 • public class Ch10_07 • { // 主程式 • public static void main(String[] args) • throws Exception • { String sour_path = "Test10_07_01.txt"; • String dest_path = "Test10_07_02.txt"; • File sour = new File(sour_path); // 建立File物件 • File dest = new File(dest_path); • if ( sour.exists() ) • { // 建立BufferedReader的輸入串流物件 • BufferedReader input = new BufferedReader( • new FileReader(sour)); • // 建立BufferedWriter的輸出串流物件 • BufferedWriter output = new BufferedWriter( • new FileWriter(dest)); • int ch; • System.out.println("正在複製檔案..." + dest); • // 複製檔案內容 • while ( (ch = input.read()) != -1 ) • output.write(ch); • input.close(); // 關閉串流 • output.close(); • System.out.println("複製檔案成功..." + dest); • } • else • System.out.println("來源檔案["+sour+"不存在!"); • } • }
InputStream/OutputStream檔案串流-說明 • 對於是二進位檔案,Java程式是使用InputStream/OutputStream類別的位元組串流來處理檔案讀取和寫入,InputStream/OutputStream類別提供對應Reader/Writer類別的方法,可以讀取和寫入位元組或位元組陣列。
InputStream/OutputStream串流的檔案處理 • 對於位元組串流的檔案I/O,Java程式是開啟FileOutputStream和FileInputStream串流,如下所示: FileOutputStream output = new FileOutputStream(file); ……… FileInputStream input = new FileInputStream(name); ……… • 上述2列程式碼分別建立輸出和輸入串流,其來源和目的都是檔案,參數可以是file的檔案路徑字串,或name的File物件。
過濾串流的檔案處理-說明 • Java的「過濾串流」(Filter Stream)是在串流間加上過濾器,以便將上方串流的資料在處理後,才送到下方的串流,如下圖所示:
過濾串流的檔案處理-範例 • DateInputStream/DataOutputStream過濾串流,屬於FilterInputStream/FilterOutputStream的子類別,如下所示: DataOutputStream output = new DataOutputStream( new FileOutputStream(file)); … … … DataInputStream input = new DataInputStream( new FileInputStream(name)); ………
隨機存取檔案的處理-說明 • 在本節前的檔案串流都屬於「循序存取串流」(Sequential Access Streams),只能如水流般依序讀取和寫入檔案。 • 「隨機存取檔案」(Random Access File)是以非循序的隨機方式存取檔案內容,如同一個位在磁碟檔案的陣列,使用索引值就可以存取元素,這個索引值稱為「檔案指標」(File Pointer)。
隨機存取檔案的處理-範例 • RandomAccessFile類別因為同時實作DataInput和DataOutput介面,所以可以讀取和寫入檔案,如下所示: RandomAccessFile input = new RandomAccessFile(file,"rw"); RandomAccessFile input = new RandomAccessFile(file,"r");
隨機存取檔案的處理-方法 • RandomAccessFile類別提供方法處理檔案指標,如下表所示:
動腦時間1:記事本 • 以下程式是上一章的記事本畫面,為”檔案_新增”, “檔案_開檔” , “檔案_存檔” 加上相對應的程式碼
/* 程式範例: Ch10_01.java */ import java.io.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import javax.swing.filechooser.*; // 繼承JFrame類別, 實作ActionListener介面 public class Ch10_01 extends JFrame implements ActionListener { private JMenuItem newItem, openItem, saveItem, exitItem; private Container c; private JTextArea area; private JScrollPane scroll; private JToolBar toolBar; // 建立JFileChooser元件 final JFileChooser jfc = new JFileChooser(); // 建構子 public Ch10_01() { super ("記事本範例"); c = getContentPane(); c.setBackground(Color.white); JMenuBar jmb = new JMenuBar(); setJMenuBar(jmb); // 新增下拉式功能表 // 第一個選單 JMenu file = new JMenu("檔案(F)"); file.setMnemonic(KeyEvent.VK_F); newItem = new JMenuItem("新檔(N)", KeyEvent.VK_N); openItem = new JMenuItem("開啟(O)", KeyEvent.VK_O); saveItem = new JMenuItem("存檔(S)",KeyEvent.VK_S); exitItem = new JMenuItem("關閉(X)",KeyEvent.VK_X); newItem.addActionListener(this); openItem.addActionListener(this); saveItem.addActionListener(this); exitItem.addActionListener(this);
file.add(newItem); file.add(openItem); file.add(saveItem); file.addSeparator(); // 分隔線 file.add(exitItem); jmb.add(file); // 新增file選單 // 第二個選單 JMenu help = new JMenu("說明(H)"); help.setMnemonic(KeyEvent.VK_H); JCheckBoxMenuItem check; check = new JCheckBoxMenuItem("線上輔助"); check.addActionListener(this); help.add(check); jmb.add(help); // 建立擁有捲動軸的文字區域元件 area = new JTextArea(15,30); scroll = new JScrollPane(area); c.add(scroll, BorderLayout.CENTER); } // 實作事件處理方法 public void actionPerformed(ActionEvent evt) { if (evt.getSource() == newItem) { area.append("開新檔案\n"); } if (evt.getSource() == openItem) { int n = jfc.showOpenDialog(Ch10_01.this); if ( n == JFileChooser.APPROVE_OPTION ) { File file = jfc.getSelectedFile(); area.append("開啟檔案名稱: "); area.append(file.getName() + "\n"); } } if (evt.getSource() == saveItem) { int m = jfc.showSaveDialog(Ch10_01.this); if ( m == JFileChooser.APPROVE_OPTION ) { File file = jfc.getSelectedFile(); area.append("儲存檔案名稱: "); area.append(file.getName() + "\n"); } } if (evt.getSource() == exitItem) System.exit(0); }
// 主程式 public static void main(String[] args) { // 建立Swing應用程式 Ch10_01 app = new Ch10_01(); // 關閉視窗事件, 結束程式的執行 app.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); app.setSize(300,200); // 設定尺寸 app.setVisible(true); // 顯示視窗 } }
import java.io.*; class RFile { public static void main(String [] args) throws Exception { FileReader fr = new FileReader("E:/wang/JAVA/Java(3)/RWFile/RWTest.txt"); BufferedReader br = new BufferedReader(fr); String str; while((str = br.readLine()) != null) { System.out.println(str); } } }
import java.io.*; class RWFile { public static void main(String [] args) throws Exception { //File ff = new File("E:/wang/JAVA/Java(3)/RWFile/WTest.txt"); FileReader fr = new FileReader("E:/wang/JAVA/Java(3)/RWFile/RWTest.txt"); FileWriter fw = new FileWriter("E:/wang/JAVA/Java(3)/RWFile/WTest.txt"); BufferedReader br = new BufferedReader(fr); BufferedWriter bw = new BufferedWriter(fw); String str; while((str = br.readLine()) != null) { bw.write(str + "\n"); } bw.close(); br.close(); } }
import java.io.*; import java.net.*; class RWWeb { public static void main(String [] args) throws Exception { String web1 = "http://www.nkmu.edu.tw/history.asp" ;//UTF-8 URL Rweb = new URL(web1); FileOutputStream fw = new FileOutputStream("E:/wang/JAVA/Java(3)/RWFile/WWebTest.txt"); BufferedOutputStream bos = new BufferedOutputStream(fw); BufferedInputStream bis = new BufferedInputStream(Rweb.openStream()); byte b[] = new byte[4096] ; int count; while((count = bis.read(b, 0, 4096)) != -1) { bos.write(b, 0, count); } bis.close(); bos.close(); } }