Java I/O 中InputStream和Reader的使用規律

當我們使用java io系統進行外部數據讀取,如網絡、文件等內容讀取很容易被複雜的類庫搞的頭昏腦脹,歲雖然要理解java的io系統以及複雜的類層次結構是一項艱難的任務,所以對於通過類庫滿足我們的需求通常是千遍一律的,比如如何讀取到互聯網上一張網頁的內容、如何讀取磁盤上一個文件的內容,這種需求的職責很單一、功能很明確,解決方案網上一搜一大把,而且大多數需要用到java io系統的需求也就是這些需求,因此即使我們不能完整的理解java io系統的細節,也不妨礙我們使用它,我們只需要從互聯網上把代碼複製到自己的程序中調用就可以了。

然而只知其然不知其所以然總歸不是一件舒服的事情,而要理解整個io系統的細節又如此艱難,因此我們可以做一個折中,去理解那些覆蓋面廣且常用但又不那麼艱深的內容,這樣是最大化投入產出比一種方案。

接下來我們談談在大多數情況下使用java io系統讀取內容的一種規律,我們來看一個代碼片段,這個代碼片段應該能代表相當一部分通過java讀取外部內容的情況了

URL url = new URL("https://www.jd.com/");
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder content = new StringBuilder();
String line = bufferedReader.readLine();
while(line != null){
  content.append(line);
  content.append("\n");
  line = bufferedReader.readLine();
}
System.out.println(content.toString());
bufferedReader.close();

我們抓取互聯網上一張網內的內容到程序中並轉換成字符串輸出, 可以將整個過程分解成一下步驟

1、獲得一個表示網頁內容的InputStream

URL url = new URL("https://www.jd.com/");
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();

InputStream非常常見,我們在很多場景下能見到他,很多系統類庫訪問外部資源返回的都是InputStream或者它的派生類,比如說文件內容讀取、網路內容讀取,甚至System.in等都會用到InputStream

 FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Desktop\\新建文本文檔.txt");

可以使用FileInputStream讀取磁盤文件,FileInputStream 是 InputStream 的一個派生類。

因此對於使用java io讀取在許多情況下就是使用InputStream

2、將InputStream轉換成InputStreamReader

從數據類型的角度講,java io系統類庫有兩種實現,一種是面向字節的InputStream/OutputStream,另一種是面向字符的Reader和Writer,字節相對與字符更加貼近系統,而字符相對於字節更加接近於用戶,因爲當我們需要輸出用戶可見的內容時更適合使用Reader/Writer系列的類庫。當然我們也可以自己處理InputStream的字節內容並轉換成字符使用,可這明顯不是明智的做法,因爲Reader/Writer已經幫我們完成任務。

Java提供了InputStreamReader類型來將InputStream轉換成Reader類型

InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf8");

InputStreamReader還有一個絕無僅有的強大功能,它可以指定讀取內容的編碼,這時其它Reader系列的類庫不具備的,比如FileReader。

使用InputStreamReader可以將InputStream的內容讀取成字符串,然而它卻並不高效。我們每調用一次InputStreamReader的read方法讀取一次內容,InputStreamReader就需要根據傳入的參數從磁盤上的文件中獲取相應的內容,那麼read的相應調用次數就等於訪問磁盤文件的次數,這是低效的行爲。

3、使用BufferedReader引入緩衝機制

BufferedReader是具備緩衝功能的一種Reader,它會預先把一部分內容從磁盤加載至內容,然而當我們讀取內容時,BufferedReader會從已經存在內存中緩衝數據中讀取內容,而不是直接訪問磁盤,噹噹前部分內容讀取完畢時,BufferedReader會從磁盤中加載新的內容至內存緩衝區,如此便能減少磁盤的訪問次數提升運行效率

 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

BufferedReader一裝飾者的身份對Reader增加緩衝區功能

4、讀取內容並輸出

StringBuilder content = new StringBuilder();
String line = bufferedReader.readLine();
while(line != null){
  content.append(line);
  content.append("\n");
  line = bufferedReader.readLine();
}
System.out.println(content.toString());

這一步非常簡單,它從bufferedReader中讀取字符串行並追加到一個StringBuilder中,最後輸出到控制檯。

總的來說的話,如果碰到要讀取外部設備內容的需求,那麼我們只要能獲得代表內容的InputStream,之後的處理大致上是相同而且簡單的,所以通過java io處理輸入內容,大致過成不外乎

  1. 獲得一個inputStream
  2. 將inputStream轉換成InputStreamReader
  3. 使用BufferedReader裝飾 InputStreamReader 來讀取具體內容
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章