標籤:
File類:
程式中操作檔案和目錄都可以使用File類來完成即不管是檔案還是目錄都是使用File類來操作的,File能建立,刪除,重新命名檔案和目錄,但File不能訪問檔案內容本身,如果需要訪問檔案本身,則需要使用輸入/輸出流,該類是位於java.io包下的
輸入與輸出IO:
輸入資料流:只能從中讀取資料,而不能向其中寫入資料(由InputStream(位元組流)和Reader(字元流)作為基類)
輸出資料流:只能向其寫入資料,而不能從中讀取資料(由OutputStream(位元組流)和Writer(字元流)作為基類)
java的io總共涉及40多個類,但都是從這四個抽象基類中派生出來的
InputStream最重要的三個read方法:
Reader中的read方法:
從這兩個抽象類別提供的方法就可以看出其實功能基本是一樣的,只是操作的資料單元不一樣而已
由於InputStream與Reader都是抽象類別,是不能進行執行個體化的,我們只能用他們的子類來建立執行個體,它們分別提供了一個子類用於讀取檔案的輸入資料流:FileInputStream和
FileReader,這兩個子類都是節點流(與處理流相對)-----會直接與指定的檔案關聯而無封裝。下面代碼示範FileInputStream使用read(byte[] b):
package xidian.sl.io;import java.io.FileInputStream;import java.io.FileReader;public class InputStreamTest { /** * 使用FileInputStream讀取該類本身 * */ public static void FileInputStreamTest() throws Exception{ FileInputStream fis = null; try{ //建立位元組輸入資料流 fis = new FileInputStream("src/xidian/sl/io/InputStreamTest.java"); //建立一個長度為1024的位元組數組來存取 byte[] bbuf = new byte[1024]; //用於儲存實際讀取的位元組數 int hasRead = 0; //使用迴圈來進行重複讀取 while((hasRead = fis.read(bbuf))> 0){ //取出位元組,將位元組數組轉化為字串輸出 System.out.println(new String(bbuf, 0 , hasRead)); } }finally{ //關閉檔案輸入資料流 fis.close(); } } /** * 使用FileReader讀取該類本身 * */ public static void FileReaderTest() throws Exception{ FileReader fr = null; try{ //建立位元組輸入資料流 fr = new FileReader("src/xidian/sl/io/InputStreamTest.java"); //建立一個長度為1024的位元組數組來存取 char[] bbuf = new char[40]; //用於儲存實際讀取的位元組數 int hasRead = 0; //使用迴圈來進行重複讀取 while((hasRead = fr.read(bbuf))> 0){ //取出位元組,將位元組數組轉化為字串輸出 System.out.println(new String(bbuf, 0 , hasRead)); } }finally{ //關閉檔案輸入資料流 fr.close(); } } public static void main(String[] args) throws Exception{ InputStreamTest.FileInputStreamTest(); InputStreamTest.FileReaderTest(); }}
可以看到這兩個子類的使用方式可以說是完全一樣的,不過這裡要注意一個問題:位元組流FileInputStream是根據位元組來讀取的,而一個中文是佔兩個位元組的,如果包含很多中文的檔案被位元組流分多次進行讀取,可能會造成亂碼,因為有可能會導致剛好將一個中文分兩次讀取,這樣就會亂碼了,因此如果中文包含多的話還是使用字元流FileReader比較好,
在位元組流與字元流之間選擇的規律:如果需要進行輸入/輸出的內容是常值內容,則應該考慮使用字元流,如果需要進行輸入/輸出的是二進位內容,則應該考慮使用位元組流,因為位元組流的功能比字元流強大,電腦中所有的資料都是二進位的,而位元組流可以處理所有的二進位檔案;
OutputStream中最重要的write方法:
Writer中最重要的write方法:
Writer類中多了兩個對字串的操作類,因此如果是直接輸出字串就選用Writer會比較的方便;
與輸入資料流一樣,輸出資料流也有兩個檔案操作的子類:FileOutputStream和FileWrite
package xidian.sl.io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileWriter;public class OutputStreamTest { /** * 使用位元組流輸出 * */ public static void FileOutputStreamTest() throws Exception{ FileInputStream fis = null; FileOutputStream fos = null; try{ //建立位元組輸入資料流 fis = new FileInputStream("src/xidian/sl/io/InputStreamTest.java"); //建立位元組輸出資料流 fos = new FileOutputStream("src/xidian/sl/io/Output.txt"); byte[] bt = new byte[40]; int hasRead = 0; //迴圈從輸入資料流中讀取資料 while((hasRead = fis.read(bt))> 0){ //每讀取一個,即寫入檔案輸出資料流,讀了多少就寫多少 fos.write(bt, 0, hasRead); } }catch (Exception e) { e.printStackTrace(); }finally{ /** * 流在關閉時會自動執行flash,將緩衝中的資料flush到物理節點中 * 所以關閉時很重要的 * */ if(fis != null){ fis.close(); } if(fos != null){ fos.close(); } } } /** * 使用字元流輸出字串會顯得比較的方便 * */ public static void FileWriteTest() throws Exception{ FileWriter fw = null; try{ //建立位元組輸出資料流 fw = new FileWriter("src/xidian/sl/io/Output.txt"); fw.write("溫州醫學院\r\n"); fw.write("資訊與管理專業\r\n"); fw.write("溫州醫學院\r\n"); fw.write("溫州醫學院\n"); fw.write("溫州醫學院"); }catch (Exception e) { e.printStackTrace(); }finally{ if(fw != null){ fw.close(); } } } public static void main(String[] args) throws Exception{ OutputStreamTest.FileOutputStreamTest(); OutputStreamTest.FileWriteTest(); }}
上面是節點流的基本使用,下面將瞭解處理流的使用,處理流會顯得更加的高效
區分節點流於處理流的方法是:只要流的構造器的參數不是一個物理節點,而是已存在的流,那這個流一定是處理流,因為所有的節點流都是直接以物理io節點作為構造器的參數、
(如file)。
舉例:PrintStream處理流來封裝FileOutputStream節點流,進行輸出,由於PrintStream類的輸出功能非常的強大,因此我們需要輸出常值內容一般都會將輸出資料流封裝成PrintStream後輸出
package xidian.sl.io;import java.io.FileOutputStream;import java.io.PrintStream;public class PrintStreamTest { public static void main(String[] args){ PrintStream ps = null; try{ //建立一個節點輸出資料流 FileOutputStream fos = new FileOutputStream("src/xidian/sl/io/Output.txt"); //以PrintStream處理流來封裝FileOutputStream節點流 ps = new PrintStream(fos); ps.println("一般字元串"); ps.println(new PrintStreamTest()); }catch (Exception e) { e.printStackTrace(); }finally{ ps.close(); } }}
其實我們一直使用的標準輸出System.out的類型都是PrintStream:
從上面的執行個體就可以看出將節點流封裝成處理流很簡單,只需調用處理流的構造方法來傳入節點流就可以了;而且看到上面流的關閉只是關閉了處理流而未去關閉節點流,這樣做是完全正確的,以後我們在關閉流的時候只需要關閉最上層的處理流即可;
字元流中有兩個特別的流來處理字串的:StringReader和StringWriter,
可以看到使用時執行個體化只需要傳入一個字串即可:例子:
package xidian.sl.io;import java.io.StringReader;import java.io.StringWriter;public class StringNodeTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String src = "你是個神"; StringReader sr = new StringReader(src); char[] chars = new char[40]; int hasRead = 0; try{ //採用迴圈的方式 while((hasRead = sr.read(chars))>0){ System.out.println(new String(chars, 0, hasRead)); } }catch (Exception e) { e.printStackTrace(); }finally{ sr.close(); } //建立StringWriter StringWriter sw = new StringWriter(40); sw.write("你是一個大神"); sw.write("你也是一個大神"); System.out.println(sw.toString()); }}
io系統提供的兩個轉換流:InputStreamReader和OutputStreamWriter,都是將位元組流轉化為字元流
在java中是使用System.in來提供鍵盤輸入的,但這個標準輸入資料流是InputStream類的執行個體:
而前面講到了當處理的是常值內容時,使用字元流會顯得比較方便,正好鍵盤輸入就是文本的操作,因此我們有必須將System.in轉換為字元流:
package xidian.sl.io;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class KeyinTest { public static void main(String[] args){ BufferedReader br = null; try{ //將System.in對象轉化為Reader對象 InputStreamReader isr = new InputStreamReader(System.in); //將節點流封裝為處理流 br = new BufferedReader(isr); String buffer = null; //採用迴圈的方式一行一行讀取 while((buffer = br.readLine()) != null){ System.out.print("輸入的內容 = "+ buffer); } }catch (Exception e) { e.printStackTrace(); }finally{ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } }}
PrintStream是有強大的輸出功能,而BufferReader有強大的輸入(即讀取),因此在操作讀取常值內容時儘可能將其轉化為BufferReader,可以方便的使用readLine()方法
接下來最為強大的檔案操作類RandomAccessFile來了,這個類既可以向檔案輸入資料,也可以輸出資料,並且他與不同的流最大的不同就是“支援檔案任意位置的訪問”,即程式可以控制讀取檔案哪個位置的內容;
從構造方法上可以看出,除了提供一個檔案或檔案名稱外還需要提供一個String參數mode,mode規定了RandomAccessFile類訪問檔案的模式:
1. “r”:以唯讀方式開啟指定檔案
2. “rw”:以讀取,寫入方式開啟指定檔案,並且檔案不存在會自動進行建立
3.“rws”與“rwd”:與“rw”類似,只是要求檔案內容或中繼資料的每個更新都同步寫入底層存放裝置
【轉】輸入/輸出流 - 全面掌握IO