生活随笔
收集整理的這篇文章主要介紹了
java流与文件——流
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【0】README
0.1) 本文描述轉自 core java volume 2, 旨在理解 java流與文件——流 的相關知識;
0.2) 輸入流和輸出流(InputStream 和 OutputStream傳輸單位是基于單字節):
- 0.2.1)輸入流:可以從其中讀入一個字節序列的對象,這個其中就叫做輸入流,即我們可以從輸入流中讀入一個字節序列的對象;
- 0.2.2)輸出流:可以從其中寫出一個字節序列的對象,這個其中就叫做輸出流,即我們可以從輸出流中寫出一個字節序列的對象;
- 0.2.3)抽象類 InputStream 和 OutputStream 構成了 輸入輸出類層次結構的基礎;
0.3)引入 抽象類Reader 和 Writer(傳輸單位是基于兩字節的Unicode碼元,每次只傳遞一個字符,見read和write方法)
- 0.3.1)problem: 因為面向字節的流不便于處理以 Unicode 形式存儲的信息;
- 0.3.2)solution:所以從抽象類 Reader 和 Writer 中繼承出來了一個專門用于處理 Unicode字符的單獨的類層次結構。這些類擁有的讀入和寫出操作都是基于兩字節的 Unicode碼元的, 而不是基于單字節的字符;(干貨——Unicode碼元==Unicode字符==兩字節)
【1】讀寫字節
1.1)InputStream 類有一個抽象方法: abstract int read()
1.2)OutputStream類有抽象方法: abstract void write(int b)
1.3) read 和 write 方法 在執行時都將阻塞,直到字節確實被讀入或寫出;這意味著如果流不能被立即訪問,則當前線程被阻塞;
- 1.3.1)available 方法: 可以檢查當前可讀入的字節數量;
- 1.3.2)close方法: 完成對流的讀寫后,用close 方法關閉它;且關閉一個輸出流的同時還會沖刷(flush)緩沖區;
(緩沖區:所有被臨時置于緩沖區中, 以便用更大的包的形式傳遞的字符在關閉輸出流時被送出, 同時減少了訪問硬盤的次數)(干貨——緩沖區的定義和作用)
- 1.3.2.1)如果不關閉文件, 那么寫出字節的最后一個包可能將永遠也不會傳遞出去;
- 1.3.3)flush方法: 沖洗緩沖區的數據到流中,最后到達文件;
【2】完整的流家族
(圖片來源: http://blog.csdn.net/hguisu/article/details/7418161)
2.1)InputStream 和 OutputStream
- 2.1.1)DataInputStream 和 DataOutputStream: 可以以二進制格式讀寫所有的基本java類型;
- 2.1.2)ZipInputStream 和 ZipOutputStream : 以常見的ZIP 壓縮格式讀寫文件;
|  |
**2.2)Reader 和 Writer** * **2.2.1)read 方法:** 返回一個 Unicode 碼元(一個在0 ~ 65535 間的整數), 或在碰到文件結尾時返回-1; * **2.2.2)write 方法:** 被調用時, 需要傳遞一個Unicode碼元;
|  |  |
**2.3)還有4個附加的接口: Closeable, Flushable, Readable, Appendable。** * **2.3.1)前兩個接口非常簡單, 它們分別擁有下面的方法:** close 和 flush 方法; * **2.3.2)InputStream, OutputStream , Read 和 Writer 都實現了 Closeable 接口;** **Attention)** * **A1)** Closeable 接口 extends AutoCloseable 接口, 因此對任何Closeable 進行操作時,都可以使用帶資源的try 語句;**(干貨——使用帶資源的try 語句的條件是該類或接口要繼承AutoCloseable接口)** * **A2)為什么要有兩個接口呢?** 因為 Closeable 接口的close方法只拋出IOException, 而 AutoCloseable.close 可以拋出任何異常; * **2.3.3)** OutputStream 和 Writer 還實現了 Flushable 接口 * **2.3.4)Readable 接口只有一個方法:** int read(CharBuffer cb) * **2.3.4.1)CharBuffer 類:** 擁有按照順序和隨機地進行讀寫訪問的方法, 它表示一個內存中的緩沖區或者一個內存映像的文件; * **2.3.5)Appendable 接口:有兩個用于添加單個字符和字符序列的方法:** Appendable append(char c) Appendable append(CharSequence s) * **2.3.6)CharSequence 接口 :**描述了一個char 值序列的基本屬性, String, CharBuffer, StringBuilder, 和 StringBuffer 都實現了它; * **2.3.7)**在流的家族中, 只有 Writer 實現了 Appendable 接口;
##**【3】組合流過濾器**
**3.1)FileInputStream 和 FileOutputStream:** 可以提供附著在 一個磁盤文件上的輸入流和輸出流, 我們只需要提供完整路徑名; **Hint)** 所有在 java.io 中的類都將相對路徑名解釋為以用戶工作目錄開始, 你可以通過調用 System.getProperty(“user.dir”) 來獲得這個信息; **Warning)** * **W1)**對于可移植的程序來說, 應該使用程序所運行平臺的文件分隔符, 通過 常量字符串 java.io.File.separator 來獲得它; * **W2)**不推薦使用 單斜杠“/” 作為文件分隔符, 而使用 “\\”; **3.2)problem 和 solution ****(干貨——這是產生組合流過濾器的原因)** * **3.2.1)problem:** 如果我們只有 DataInputStream, 我們就只能讀入數值類型: DataInputStream din = … double s = din.readDouble(); 正如 FileInputStream 沒有任何讀入數值類型的方法一樣, DataInputStream 也沒有任何從文件中讀取數據的方法: * **3.2.2)solution:** java使用了一種機制來分離這兩種職責。某些流(如 FileInputStream 和 由 URL 類的openStream 方法返回的輸入流) 可以從文件和其它位置獲取字節, 而其他的流(如 DataInputStream 和 PrintWriter) 可以將字節組裝到更有用的數據類型中; * **3.2.3)我們需要對它們進行組合, 看個荔枝:**為了從文件中讀取數組,需要創建一個FileInputStream , 然后將其傳遞給 DataInputStream 的構造器:
FileInputStream fin =
new FileInputStream(
"a.dat");
DataInputStream din =
new DataInputStream(fin);
double s = din.readDouble(); 
**3.3)嵌套過濾器添加多重功能** * **3.3.1)請求一個數據塊并將其置于緩沖區中會更加高效, 添加這種緩沖機制:** DataInputStream din = new DataInputStream(new BufferedInputStream(new FileInputStream(“a.dat”))); * **Attention)**我們把 DataInputStream 放置在 構造器鏈 的最后,因為我們希望 使用 DataInputStream 的方法, 并且希望它們能夠帶有緩沖機制的 read 方法; * **3.3.2)PushbackInputStream(可回推輸入流)** PushbackInputStream pbin = new PushbackInputStream(new BufferedInputStream(new FileInputStream(“a.dat”))); * **3.3.2.1) 現在,預讀下一個字節: ** int b = pbin.read(); * **3.3.2.2)如果不滿足,將其推回流中: ** pbin.unread(b); * **3.3.2.3)**但是讀入和推回是可應用于可回推(pushback) 輸入流的僅有 的方法; * **3.3.2.4)如果你需要預先瀏覽并且還可以讀入數字, 那么你就需要一個既是可回推輸入流,又是一個數據輸入流的引用;**
PushbackInputStream pbin =
new PushbackInputStream(
new BufferedInputStream(
new FileInputStream(
"a.dat")));
DataInputStream din =
new DataInputStream(pbin); 
| 注意: (轉自, http://blog.csdn.net/u010700335/article/details/40155053) 如果文件串的最后一個字符是中文,使用mark()中的長度設為file.length() 如果文件的最后一個字符串是英文或數字,則java.io.IOException: Mark invalid,使用mark()中的長度設為file.length()+1 mark用于標記當前位置;在讀取一定數量的數據(小于readlimit的數據)后使用reset可以回到mark標記的位置;FileInputStream不支持mark/reset操作;BufferedInputStream支持此操作; mark(readlimit)的含義是在當前位置作一個標記,制定可以重新讀取的最大字節數,也就是說你如果標記后讀取的字節數大于readlimit,你就再也回不到回來的位置了;通常InputStream的read()返回-1后,說明到達文件尾,不能再讀取。除非使用了mark/reset。。 |
- 3.3.3)看個荔枝: 可以通過一個 ZIP 壓縮文件中通過使用下面的流序列讀入數字:
ZipInputStream zin =
new ZipInputStream(
new FileInputStream(
"a.zip"));
DataInputStream din =
new DataInputStream(zin);
總結
以上是生活随笔為你收集整理的java流与文件——流的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。