文件輸入流 FileInputStream
這是一個簡單的FileInputStream示例:
InputStream input = new FileInputStream("D:\\input.txt");
int data = input.read();
while(data != -1) {
//do something with data...
doSomethingWithData(data);
data = input.read();
}
input.close();
注意:爲了代碼清晰,這裏並沒有考慮處理異常的情況,IO 異常處理有專門的介紹。
FileInputStream 構造器
FileInputStream 類有三個不同的構造函數,可用於創建 FileInputStream 實例。
-
構造函數將一個包含文件系統中要讀取的文件所在的路徑 String 作爲參數:
FileInputStream fileInputStream = new FileInputStream( "D:\\1.txt");
注意路徑需要雙反斜槓\\
,因爲反斜槓是Java字符串中的轉義字符,通過此方式獲得單個反斜槓。
在unix上,文件路徑可能如下所示:
String path = "/home/czwbig/data/thefile.txt";
注意使用正斜槓/
作爲目錄分隔符。 這是在 unix 上編寫文件路徑的方法。 實際上,Java 也會理解在 Windows 上使用/
作爲目錄分隔符,例如new FileInputStream("D:/out.txt")
-
構造函數將 File 對象作爲參數。 File 對象必須指向要讀取的文件。 這是一個例子:
String path = "D:\\out.txt";
File file = new File(path);
FileInputStream fileInputStream = new FileInputStream(file);
應該使用哪個構造函數取決於在打開 FileInputStream 之前具有該路徑的形式。 如果您已經有一個 String 或 File ,只需按原樣使用它。 將 String 轉換爲 File 或將 File 轉換爲 String 沒有特別的好處。
- public FileInputStream(FileDescriptor fdObj)
通過使用文件描述符 fdObj 創建一個 FileInputStream,該文件描述符表示到文件系統中某個實際文件的現有連接。不常用。
read(byte[])
作爲 InputStream 的子類,FileInputStream 還有兩個 read() 方法,可以將數據讀入字節數組。 可以在我的有關 InputStream 的文章中閱讀,不展開了。
close()
建議使用 try 自動關閉,參考 IO 異常處理章節。
文件輸出流 FileOutputStream
這是一個簡單的 FileOutputStream 示例:
OutputStream output = new FileOutputStream("D:\\out.txt");
while(moreData) {
int data = getMoreData();
output.write(data);
}
output.close();
FileOutputStream 構造器
和 FileInputStream 的 3 個構造器差不多,參考上面即可。
另外多了兩個構造方法:
- FileOutputStream(File file, boolean append) ;
- FileOutputStream(String name, boolean append) ;
參數 append :如果不給出 append 參數,其值默認是 false 的,即默認是覆蓋模式。如果爲 true,則將字節寫入文件末尾處,而不是寫入文件開始處,這樣就能不覆蓋文件,而是追加內容。
所以,在新建 FileOutputStream 對象的時候,要非常小心,只要沒有指定 append 爲 true ,那麼只要 FileOutputStream 對象創建成功,對應的文件會被立即清空。
如代碼:OutputStream outputStream = new FileOutputStream("D:\\test\\1.txt");
,執行後對應的 1.txt 文件(如果存在)會立刻被清空,而不管有沒有調用 OutputStream 的 write() 方法。
write(…) and flush()
參考 OutputStream 。
使用 RandomAccessFile 隨機訪問文件
這裏的隨機訪問是指,指定任何一個位置,都能夠訪問它;而不是不確定的隨機訪問某一個位置。
在使用 RandomAccessFile 類之前,必須實例化它。它有兩個構造器,如下:
- RandomAccessFile(File file, String mode)
- RandomAccessFile(String name, String mode)
實例:
RandomAccessFile file = new RandomAccessFile("c:\\data\\file.txt", "rw");
參數:
file、name- 該文件對象
mode - 訪問模式,如下表:
值 | 含意 |
---|---|
“r” | 以只讀方式打開。調用結果對象的任何 write 方法都將導致拋出 IOException。 |
“rw” | 打開以便讀取和寫入。如果該文件尚不存在,則嘗試創建該文件。 |
“rws” | “rw” + “sync”,另外還要求對文件的內容或元數據的每個更新都同步寫入到底層存儲設備。 |
“rwd” | “rw” + “data”,另外還要求對文件內容的每個更新都同步寫入到底層存儲設備。 |
“rwd” 模式
可用於減少執行的 I/O 操作數量.使用 “rwd” 僅要求更新要寫入存儲的文件的內容;使用 “rws” 要求更新要寫入的文件內容及其元數據,這通常要求至少一個以上的低級別 I/O 操作。
“rws” 和 “rwd” 模式
如果該文件位於本地存儲設備上,那麼當返回此類的一個方法的調用時,可以保證由該調用對此文件所做的所有更改均被寫入該設備。這對確保在系統崩潰時不會丟失重要信息特別有用。如果該文件不在本地設備上,則無法提供這樣的保證。
在文件中跳轉
要在 RandomAccessFile 中的特定位置讀取或寫入,必須首先將文件指針放在要讀取或寫入的位置。 這是使用 seek() 方法完成的。 可以通過調用 getFilePointer() 方法獲取文件指針的當前位置。
read() 方法將文件指針遞增爲指向剛剛讀取的字節後文件中的下一個字節! 這意味着可以繼續調用 read() 而無需手動移動文件指針。
看如下例子:
public class RandomAccessFileExample {
public static void main(String[] args) throws IOException {
// out.txt 此時的文件內容爲 "123456789"
RandomAccessFile file = new RandomAccessFile("D:\\out.txt", "rw");
System.out.println("pointer: " + file.getFilePointer()); // 輸出 pointer: 0
System.out.println("char: " + (char) file.read()); // 輸出 char: 1
System.out.println("pointer: " + file.getFilePointer()); // 輸出 pointer: 1
file.seek(4); // 下標從 0 開始的,讓其指向第 5 個字節
System.out.println("pointer: " + file.getFilePointer()); // 輸出 pointer: 4
System.out.println("char: " + (char) file.read()); // 輸出 char: 5
System.out.println("pointer: " + file.getFilePointer()); // 輸出 pointer: 5
file.close();
}
}
read & write
從 RandomAccessFile 讀取是使用其衆多 read() 方法之一完成的。
方法 | 描述 |
---|---|
read(byte[] b) | 將最多 b.length 個數據字節從此文件讀入 byte 數組。 |
readByte() | 從此文件讀取一個有符號的八位值。 |
readChar() | 從此文件讀取一個字符。 |
readFully(byte[] b) | 將 b.length 個字節從此文件讀入 byte 數組,並從當前文件指針開始。 |
readLine() | 從此文件讀取文本的下一行。 |
skipBytes(int n) | 嘗試跳過輸入的 n 個字節以丟棄跳過的字節。 |
setLength(long newLength) | 設置此文件的長度。 |
writeChars(String s) | 按字符序列將一個字符串寫入該文件。 |