? ? ? ? 我們知道,文件是寫在磁盤中的,而程序的運行又要借助于內存。那么怎么實現內存和磁盤的“互動”呢?這就要借助“流”來實現了。
? ? ? ? 內存具體指的就是我們的java程序,而磁盤具體指的是我們的文件。從磁盤到內存叫輸入,從內存到磁盤叫輸出:
? ? ? ? 流就相當于一位“外賣小哥”,在內存和磁盤之間來回穿行,攜帶數據。流有以下幾種分類:
? | 字節流 | 字符流 |
輸入流 | InputStream | Reader |
輸出流 | OutputStream | Writer |
? ? ? ? 如果按照流的角色,還可以分為節點流,處理流/包裝流。今天我們要講的是字節流中的輸入流。
? ? ? ? 字節流適用于所有類型數據,因為它是對數據最底層的操作,直接以字節為單位進行讀寫的。我們在d盤里創建一個Test97.txt文件并在其中寫入“Hello,world”。
? ? ? ? 我們創建一個文件輸入流FileInputStream對象,將文件路徑放到其中去,我們的目的是讀取到文件中的數據:
String FilePath = "d:\\Test97.txt";
FileInputStream fileInputStream0 = new FileInputStream(FilePath);
? ? ? ? 我這里創建了一個ArrayList數組list存儲數據,并使用read()方法讀取數據。注意,read方法一次只能讀取一個字節的數據,并且返回值為int類型。當讀取完畢時,會返回值-1。
//接收數據
ArrayList<Character>list = new ArrayList<>();
int read0 = 0;
while((read0 = (fileInputStream0.read())) != -1) {list.add((char)read0);
}
? ? ? ? 創建好一個Character類型的數組,再將接受到的數據進行強制類型轉換,放進數組中。
? ? ? ? 這里為什么我要用read0來接收數據呢?因為如果直接使用fileInputStream0.read()!=-1方法來判斷是否接受完畢,再使用list.add((char)fileInputStream0.read());接收數據,實際上總共接受了兩次數據,會導致接收的數據錯誤。
? ? ? ? 最后需要關閉文件流,釋放資源:
fileInputStream0.close();
? ? ? ? 可以遍歷查看數組中的元素是否為我們想要的內容。
? ? ? ? read還提供了一種常用的構造方法:read(byte[] b),在read里傳入一個byte類型的數組,將文件內容讀取到byte類型數組中去,增強了文件讀取效率。
? ? ? ? 這里我們創建另一個FileInputStream對象,并創建一個長度為5的byte類型數組來接受數據:
String FilePath = "d:\\Test97.txt";
FileInputStream fileInputStream1 = new FileInputStream(FilePath);
//創建接受的byte數組
byte[] b = new byte[5];
? ? ? ? 這里要注意了,讀取文件內容的長度最多不超過b.length個字節。超出的字節可以被下一次讀取到,但同樣不超過b.length個字節。
? ? ? ? 如果read(byte[] b)方法讀取正常,會返回實際讀取字節數。
//直接讀取
fileInputStream1.read(b);
//釋放資源
fileInputStream1.close();
? ? ? ? 同樣可以遍歷b數組并強制類型轉換來查看是否導入成功:
//轉成char類型
for(byte i:b) {System.out.print((char)i);
}
? ? ? ? 好了,字節輸入流就講到這里,下次我們聊一聊字節輸出流。
? ? ? ??
????????
?