檔案處理.

Slides:



Advertisements
Similar presentations
软件编程基础 一、程序的编辑 Java 源程序是以 Java 为后缀的简单的文本文件,可以用各种 Java 集成开发环境中的源代码编辑器来编写,也可以用其他文 本编辑工具,如 Windows 中的记事本或 DOS 中的 EDIT 软件等。 利用文字编辑器编写下列程序 public class Hello.
Advertisements

Java 程序分类 Java Application :是完整程序,需要独立的解 释器解释运行;以 “.java” 为后缀的文件,以 main() 方法作为程序入口,由 java 编译器编译生 成字节码,由 Java 解释器加载执行字节码。 Java Applet 没有 main() 方法作为程序入口,是嵌在.
单元二:面向对象程序设计 任务二:借书卡程序设计.
第四章 类、对象和接口.
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
项目6 通用堆栈.
Java程序设计教程 第一讲 Java概述.
Java的程式架構與基本觀念 Java語言的歷史 Java程式的開發環境 Java程式的架構 輸出與輸入物件之使用 工具使用方法介紹
四資二甲 第三週作業 物件導向程式設計.
《Java程序设计之网络编程》 教学课件 重庆大学计算机学院
第五章 字符串.
視窗程式設計 2. 視窗版面配置 Chih Hung Wang Reference:
第二章 JAVA语言基础.
第二部分 Java语言基础篇 第4章 Java语言与面向对象 (之一).
例外與檔案處理 例外處理 拋出例外 串流 Stream FileReader、FileWriter
Ch07 介面與多重繼承 物件導向程式設計(II).
輸入輸出 學習目標 瞭解串流與輸入輸出的關係 認識InputStream、OutputStream繼承架構
创意源自激情,技术成就梦想 畅翼创新俱乐部 2012年春俱乐部第三次技术培训 赵程.
第7章 输入输出处理.
第三章 控制结构.
程式設計實作.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
第5章 面向对象程序设计 本章要点 5.1 面向对象程序设计概述 5.2 Java语言的面向对象程序设计 5.3 方法的使用和对象数组
Java语言程序设计 清华大学出版社 第9章 网络通信.
Java 第28讲:建立删除文件 主讲教师:李焱 讲师.
Java基础 JavaSE异常.
2018/11/20 第一章 Java概述 武汉大学计算机学院计算机应用系 2018/11/20 14:33.
第3章 語法入門 第一個Java程式 文字模式下與程式互動 資料、運算 流程控制.
Multithread 多執行緒 I/O Lecturer:楊昌樺.
JAVA 编 程 技 术 主编 贾振华 2010年1月.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
程式設計實作.
第四章 基本輸出入 Java應用程式的輸出入介面有三種,分別是命令提示字元視窗、AWT元件、及Swing元件。本單元先介紹命令提示字元視窗,AWT請看第16、17章,Swing請看第20章。 輸入 輸出.
抽象类 File类 String类 StringBuffer类
Java程序设计 第18章 二进制I/O.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第九章 输入/输出流.
程式撰寫流程.
Java语言程序设计 第五部分 Java异常处理.
Java程序设计 第9章 继承和多态.
第七章 输入/输出 标准输入输出 流式I/O基础 文件 随机存取文件 对象输入/输出流.
第12章 JSP的檔案與電子郵件處理 12-1 伺服端的檔案處理 12-2 伺服端檔案的讀取與寫入 12-3 客戶端的檔案上傳
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
實作輔導 3 日期: 4/14(星期六) 09:10~12:00、13:10~16:00
3.1 数据类型 3.2 标识符与关键字 3.3 常量 3.4 变量 3.5 运算符与表达式 3.6 一个编程实例
异常及处理.
第一章 Java语言概述.
C/C++/Java 哪些值不是头等程序对象
第五讲 JSP中的文件操作(1) 教学目的 本讲主要讲述JSP中使用Java输入、输出流实现文件的读写 操作 。 知识要点
* 單元:電腦與問題解決 主題:Java物件導向程式設計-類別與物件 台南縣國立善化高中 蕭嘉民 老師
4.2通讯服务模块线程之间传递信息 信息工程系 向模军 Tel: QQ:
Java程序设计 第8章 字符串和文本I/O.
第二章Java基本程序设计.
第二章 Java基本语法 讲师:复凡.
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
2019/5/3 JAVA Socket(UDP).
第二章 Java语法基础.
第二章 Java基本语法 讲师:复凡.
龍老師我不會Debug QQ.
第二章 Java基本语法 讲师:复凡.
助教:廖啟盛 JAVA Socket(UDP) 助教:廖啟盛
PPT注意事项: 当前PPT课件文件必须和提供的源代码文件夹“代码”在同一目录中即不要移动文件夹“代码”的默认位置。
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
第4讲 类和对象、异常处理 ggao.
只要功夫深 铁杵磨成针 —— 写在前面的话.
迴圈(重複性結構) for while do while.
判斷(選擇性敘述) if if else else if 條件運算子.
第二章 Java基础语法 北京传智播客教育
第二章 Java基本语法 讲师:复凡.
Summary
Presentation transcript:

檔案處理

前言 目前所學的:從使用者取得資料,把資料放在物件或者陣列,然後對這些資料進行處理;在處理完資料之後,將結果列印出來 可是,程式結束後,資料都不見了;如果之後我們需要再次處理相同的資料的時候,怎麼辦? 再讓使用者輸入一次嗎?先不說輸入的過程有可能會輸入錯誤的資料,更何況如果這些資料有上千筆、甚至上萬筆的時候,那 … 我們需要一種機制,把處理的資料儲存起來,然後需要的時候,再把資料讀進來 檔案 資料庫

資料串流 在 Java,串流除了用在檔案的輸出/輸入之外,其實它用在所有的 I/O(Input/Output),例如:印表機、網路連線、資料庫的輸入/輸出等等。

串流 依據處理的資料單位,串流分成兩大類 一類是位元組串流(Byte Stream),其讀寫的單位為位元組(byte) 另一類是字元串流(Character Stream),其讀寫的單位是字元(character) 依據處理的資料流向,串流又可以分成輸入串流(Input Stream)以及輸出串流(Output Stream) Stream 是單行道

串流類別 所有的串流類別都是屬於 java.io 的套件 所有的位元組串流都有一個父類別,依照輸入以及輸出分別定義了 InputStream 和OutputStream 兩個類別。 如果要讀取二進位的檔案,請使用 InputStream 的子類別;如果要輸出一個二進位的檔案,請使用OutputStream 的子類別 所有的字元串流也有一個父類別,依照輸入以及輸出分別定義了 Reader 和 Writer 兩個類別。 如果是讀/寫純文字資料,請使用 Reader/Writer 的子類別

串流類別 不論是 InputStream/OutputStream 或者Reader/Writer,一般都不建議直接使用這四個類別以及其子類別(direct subclasses),因為這些子類別被歸類為低階串流,它們所提供的方法都很少也不好用 一般建議使用的串流類別大多屬於這些類別的子孫類別,我們稱之為過濾串流(Filter Stream)

將位元組轉換成字元 有可能把位元組串流轉換成字元串流? Java 提供了兩個互轉的類別 InputStreamReader:將位元組串流轉成字元串流 OutputStreamWriter:將字元串流轉成位元組串流

檔案的輸出與輸入 檔案(或者說所有 I/O)處理的三個主要步驟: 一個實際的檔案(或者 I/O 設備)在程式中由一個串流物件代表 開啟檔案 檔案資料的處理 關閉檔案 一個實際的檔案(或者 I/O 設備)在程式中由一個串流物件代表 例如:螢幕由 System.out 物件代表 因此,利用物件來讀取/寫出資料,相當於對檔案進行讀取/寫出的動作。

檔案的輸出與輸入 開啟檔案 檔案資料的處理 關閉檔案 一般來說,檔案格式處理前都已經知道。 輸入:若出現例外,可能檔案不存在、沒有存取權限等。 輸出:若檔案不存在,則產生新檔;若檔案存在,則刪除舊檔並產生新檔。若出現例外,可能有一個與檔案名稱相同的目錄、硬碟(或者配額)滿了、沒有足夠的權限等。 檔案資料的處理 一般來說,檔案格式處理前都已經知道。 大多不知道會有幾筆資料,因此一般使用迴圈處理資料並需要知道判斷 EOF(End of File)的方式。 請留意檔案的編碼:請使用相對應的串流類別 關閉檔案 非常重要。例如,連結資料庫的連線一般都有上限的限制,如果不關閉,…

檔案的輸出與輸入 檔案輸入/輸出的相關串流類別: FileInputStream/FileOutputStream FileReader/FileWriter

開啟檔案 以檔案名稱來開啟一個輸出檔案,而該檔案的開啟方式如下: FileWriter f = new FileWriter(“test.txt”); 由於 PrintWriter 所提供的方法非常多,我們希望使用它;產生 PrintWriter 物件的方式如下: PrintWriter p = new PrintWriter(f); 有了 p 之後,我們就可以使用 println()、format()、或者 printf() 等方法將資料輸出到test.txt 中

13 PrintWriter p = new PrintWriter(f); 15 // 資料處理:將資料輸出 16 p.println(1234); 17 p.println(21.34); 18 p.println("Hello, world."); 20 Worker w = new Worker("John", 32000); 21 p.println(w.getName()); 22 p.println(w.getSalary()); 24 // 關閉檔案 25 p.close(); 26 } 27 } 01 import java.io.*; 03 public class TestFileWriter1 { 04 public static void main(String[] args) { 05 // 開啟檔案 06 FileWriter f = null; 07 try { 08 f = new FileWriter("test.txt"); 09 } catch (IOException e) { 10 System.out.println("檔案開啟錯誤"); 11 System.exit(-1); 12 }

執行畫面

執行畫面 FileWriter f = new FileWriter(“test.txt”, true);

練習題 請修改 TestFileWriter1 使得每一次執行的資料會不斷的加到 test.txt 的最後。 我們想把 PrintWriter 改成BufferedWriter,請修改 TestFileWriter1。 依據相同的概念,但是請使用 FileOutputStream 來處理檔案,請對 TestFileWriter1 作必要的修改。

讀取純文字檔 由於 test.txt 是純文字檔,開啟輸入檔案的方式如下 FileReader f = new FileReader(“test.txt”); 由於大部分的文字檔案都是一行一行的,所以我們就使用一次可以讀一行的BufferedReader來讀取資料,而產生一個BufferedReader物件的方式如下 BufferedReader r = new BufferedReader(f); 由於我們事先知道資料的內容依序是整數、浮點數、字串、以及利用 Worker 的 get 方法所取得的字串和整數,所以我們讀進資料之後,就可以依照其資料型態作進一步的處理

BufferedReader 由於 BufferedReader 會把讀進來的資料先暫時放在一個 Buffer 裡,這樣處理速度會比較快,而且它還提供了 readLine() 方法

TestFileReader1 04 public static void main(String[] args) { 05 // 開啟檔案 05 // 開啟檔案 06 FileReader f = null; 07 try { 08 f = new FileReader("test.txt"); 09 } catch (IOException e) { 10 System.out.println("檔案開啟錯誤"); 11 System.exit(-1); 12 } 13 BufferedReader p = new BufferedReader(f); 14

19 int num1 = Integer.parseInt(input); 20 input = p.readLine(); 15 // 資料處理:將資料讀進來併處理 16 String input; 17 try { 18 input = p.readLine(); 19 int num1 = Integer.parseInt(input); 20 input = p.readLine(); 21 double num2 = Double.parseDouble(input); 22 System.out.println("Total: " + (num1 + num2)); 23 24 input = p.readLine(); 25 System.out.println(input); 26 27 input = p.readLine(); 28 Worker w = new Worker(input, Integer.parseInt(p.readLine())); 29 w.setSalary(w.getSalary() + 1200); 30 w.setName(w.getName() + " Steward"); 31 System.out.println(w.getName() + " 薪資為 " + w.getSalary()); 32 } catch (IOException e) { 33 System.out.println("資料讀取錯誤"); 34 System.exit(-2); 35 } 雖然當初儲存前是整數,但是實際儲存的方式是字串,因此需要做適當的轉換。

TestFileReader1 37 // 關閉檔案 38 try { 39 p.close(); 37 // 關閉檔案 38 try { 39 p.close(); 40 } catch (IOException e) { 41 System.out.println("檔案無法關閉"); 42 } 43 } 44 }

輸出/輸入整數、物件 有沒有可能將原始資料型態的資料寫入檔案,然後以原始資料型態的方式將資料讀入? 可以使用 DataInputStream 和 DataOutputStream。 不在本課程的範圍,請自行學習。 有沒有可能直接將物件寫入檔案,然後將物件直接讀入? 可以使用 ObjectInputStream 和 ObjectOutputStream。

範例 假設總公司的人事資料系統每隔一段時間就會收到從各個分公司傳過來的 Worker 薪資資料(以便經由銀行匯款方式給附薪資)。薪資資料儲存在一個名為 person.dat 的檔案,這些檔案有可能是空的,事先也不知道會有多少筆。但是如果有資料的話,其格式如下: s 采壹林 65000 h 無中線 132 s 舟截輪 67000

範例 person.dat 第一個欄位,代表員工類別,s 代表SalaryWorker,而 h 代表 HourlyWorker 第二個欄位代表員工姓名 第三個欄位代表薪資(如果是 s 的話)或者工作時數(如果是 h 的話) 假設這個人事系統在讀完資料之後,除了需要將每一個人的薪資清單列印出來之外,還會把這一次檔案內的薪資總額列印出來。

程式說明 由於讀進來的每一筆資料都有三個欄位,因此程式必須能夠把這三項資料分別 把資料分開的方式有好幾種,例如利用一個類別 java.util.StringTokenizer 一個 StringTokenizer 的物件能夠利用預設的分隔符號(空格)將一個字串的資料項目分開 可呼叫 nextToken() 方法 讀完一個 token,指標會移到下一個 token

練習題 請依照下列需求,修改 TestFileReader: 假設讀完資料之後,將每一個人的薪資清單輸出到一個叫做 salary.dat 的檔案中,而且每一次新處理的資料都會加到 salary.dat 的最後。 假設每一筆資料讀進來之後,就把資料存放到一個ArrayList (或者陣列)的物件;然後利用 ArrayList (或者陣列) 來處理資料,例如排序。 假設 person.dat 的分隔符號從空格改成分號(;),請善用 StringTokenizer,重新修改你的程式。

練習題 繼續之前 Circle/Rectangle 的範例, 請設計一套系統,使得使用者可以從檔案 shape.txt 讀取[任意/固定]個 Circle 或者 Rectangle 物件,檔案格式如下: C 4.2 R 1.2 4.5 C 3.1 C 代表 cirlce,而 R 代表 rectangle 請依照之前的範例,將讀取的物件的面積、周長等資料列印出來 請將使用者輸入的 Circle 或者 Rectangle 物件新增至 shape.txt 中(保留原來的資料)

File 類別 利用 File 物件來開啟檔案 一個 File 物件可以代表一個檔案或者目錄,它所提供的方法包含目前的檔案路徑、檔案大小、新增/刪除檔案(或者目錄)等 開啟一個 File 物件的方式 File f = new File(“TestFile1.java”);

執行畫面

指定 File 路徑 在 Unix 類的作業系統中,檔案絕對路徑名稱為 Windows 類的作業系統中,檔案絕對路徑名稱為 File f = new File(“/home/MyBooks/Java101/Ch13/I4/TestFile1.java”); Windows 類的作業系統中,檔案絕對路徑名稱為 File f = new File(“D:\\MyBooks\\Java101\\Ch13\\I4\\TestFile1.java”); 或者 File f = new File(“D:/MyBooks/Java101/Ch13/I4/TestFile1.java”);

範例 (指定 File 路徑) 01 import java.io.*; 02 03 public class TestFile2 { 04 public static void main(String[] args) { 05 File f = new File("d:/MyBooks/Java101/Ch13/I4"); 06 System.out.println(f.getName() + " 的父目錄是 " + f.getParent()); 07 if(f.isDirectory()) 08 System.out.println(f.getName() + " 是一個目錄"); 09 displayDirectory(f); 10 11 File newd = new File(f.getAbsolutePath() + "/newDir"); 12 newd.mkdir(); displayDirectory(f); }

範例 (指定File路徑) 16 public static void displayDirectory(File f) { 17 // 顯示目錄內檔案 18 File[] list = f.listFiles(); 19 for(int i=0; i<list.length; i++) { 20 if(list[i].isDirectory()) 21 System.out.println("<" + list[i].getName() + ">"); 22 else 23 System.out.println(list[i].getName()); 24 } 25 } 26 }

執行結果

練習題 請改寫 TestFile2 使得檔案名稱的顯示類似 “dir /w” 的格式。 請寫一個程式 Dir.java,使得使用者可以利用 ”java Dir dir1 dir2 … dirN” 的指令來顯示目錄 dir1、dir2、…、dirN 內的檔案名稱。如果某個目錄不存在(利用 exists()方法),該目錄輸出的部份會顯示”目錄不存在”。 請寫一個程式 Copy.java,使得使用者可以利用 ”java Copy file1 file2” 的指令將 file1 複製到 file2。如果 file2 已經存在,程式必須問使用者要覆蓋原檔案、另外取名、或者取消。由於我們不知道 file1 是不是文字檔,因此我們建議你使用位元組串流相關類別(也就是FileInputStream/FileOutputStream 的相關類別)來複製,複製的方式就是讀一個位元組進來,就寫一個位元組出去。

JFileChooser 類別 java.swing.JFileChooser 是一個 Swing 的類別,該類別提供使用者一個圖型介面來選擇檔案。產生 JFileChooser 物件的方式如下: JFileChooser fc = new JFileChooser(); 預設的目錄:Windows 是”我的文件”,而 Unix 是使用者的”家目錄”(home directory) 利用 fc.showOpenDialog(null); 則會出現如下畫面的檔案開啟視窗讓使用者選擇檔案

JFileChooser 類別

範例 假設我們希望修改 TestFile1 的程式,使得使用者能夠利用檔案開啟視窗在目前這個目錄內選擇某個文字檔,而且在開啟該檔案後,程式會將檔案的內容呈現在視窗上

為了不必要的、且非常快速的產生”孤兒”物件,一般會使用 StringBuffer 類別。 之前的作法是:每次處理完一個字串就立即輸出;而這裡的作法是先累積到一個字串,然後一次輸出。哪一種好?

執行結果

程式說明 一旦檔案選擇完畢,由以上執行畫面所示,使用者不是選擇右下角的”開啟”按鈕,就是”取消”按鈕。如果使用者選擇”取消”按鈕,則 showOpenDigloa() 方法回傳一個 JFileChooser.CANCEL_OPTION 反之,如果使用者點選”開啟”按鈕,則showOpenDigloa() 方法回傳一個 JFileChooser.APPROVE_OPTION

執行畫面 本範例在使用者選擇了TestFile2.java之後的執行畫面如右:

顯示特定副檔名的檔案 要使得檔案開啟視窗只顯示擁有特定副檔名的檔案,我們需要藉助 使用方式如下: javax.swing.filechooser.FileNameExtensionFilter 類別 使用方式如下: import javax.swing.*; import javax.swing.filechooser.*;

顯示擁有特定副檔名 呼叫 fc.showOpenDialog() 之前,將副檔名過濾器設定到 fc 物件,設定方式: FileNameExtensionFilter filter = new FileNameExtensionFilter("Java 原始碼", "java"); fc.setFileFilter(filter);

執行結果

FileNameExtensionFilter 第一個引數為顯示副檔名的描述 第二個引數為副檔名;例如要顯示所有副檔名為 .java 的檔案,第二個引數就設定為 ”java” 如果某一種檔案型態的副檔名有兩種以上,我們就將可能出現的副檔名,全部放在包含第二個引數的後面,而且每一個引數之間以逗點分開,用法如下: FileNameExtensionFilter filter = new FileNameExtensionFilter(“網頁”, “html”, “htm”);

練習題 請修改 TestFile3.java 修改成開啟檔案視窗只顯示副檔名為 html 或者 htm 的檔案,然後把使用者選擇的網頁內容顯示在螢幕上。 請修改 TestFileReader,使得 使用視窗介面來選擇檔案,而不是預設的 person.dat 使用視窗介面來選擇輸出檔案的名稱,而不是預設的 salary.dat(你開始使用 API 了嗎?)