你好!第 3 級的課程和任務教您如何在控制台上顯示內容,以及如何從鍵盤上讀取數據。
從鍵盤上閱讀:“讀者” - 1
您甚至學會了使用以下複雜構造來完成此操作:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
但是我們還沒有回答一個問題。

這究竟是如何運作的?

實際上,程序很少是完全獨立的。它們與其他程序、系統、互聯網等進行通信。“通信”主要是指“交換數據”。也就是說,它們接收一些外部數據,同時也在某處發送內部程序數據。程序交換數據的例子在日常生活中比比皆是。例如,許多網站允許您使用 Facebook 或 Twitter 帳戶登錄而不是註冊。在這種情況下,兩個程序(例如 Twitter 和您正在登錄的網站)交換必要的數據。最後的結果就是你登錄成功了。“stream”這個詞用於描述數據交換的過程。這個名字從何而來?根據您的經驗,“溪流”可能更多地與河流相關,而不是與編程相關。這絕非偶然 :) 流本質上是一段移動的數據。換句話說,在編程中,流動的不是水,而是字節和字符形式的數據。我們可以從數據流中接收數據位,然後使用它們。同樣,我們將使用水/流量類比:您可以從河中舀水來煮湯、滅火或澆花。Streams 讓您可以使用任何數據源:無論是 Internet、您計算機的文件系統還是其他任何東西——都沒有區別。流是一種通用工具。它們允許程序從任何地方(輸入流)接收數據並將其發送到任何地方(輸出流)。他們的任務是相同的:從一個地方獲取數據並將其發送到另一個地方。有兩種類型的流:
  1. 輸入流用於接收數據
  2. 輸出流用於發送數據。
InputStream在 Java 中,這些流由和類 實現OutputStream。但是流可以用另一種方​​式分類。除了輸入和輸出流,我們還談到字節流字符流。這裡的意思應該很清楚了:字節流以一組字節的形式發送信息,而字符流以一組字符的形式發送信息。在本課中,我們將詳細介紹輸入流。我將在課程結束時提供有關輸出流信息的鏈接。您可以自己閱讀它 :) 現在看一下這段代碼:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
在上課的時候,你不覺得這句話很嚇人嗎?:) 一旦我們探索了它的工作原理,情況就不一樣了。讓我們把事情做好。我們將從最後開始。 System.in是一個InputStream對象,是我們之前談到的類的一個實例。它是鏈接到系統輸入設備(鍵盤)的輸入流。順便說一句,您間接熟悉此流。畢竟,你經常使用它的“同事”—— System.outSystem.out是系統輸出流。它用於通過System.out.println()您經常使用的您最喜歡的方法將數據輸出到控制台 :) System.out是一個用於將數據發送到控制台的流,而System.in用於從鍵盤獲取數據。一切都很簡單 :) 更重要的是,我們可以在沒有這個巨大結構的情況下從鍵盤讀取數據。我們可以簡單地寫System.in.read()

public class Main {

   public static void main(String[] args) throws IOException {

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
該類InputStream(記住,System.in是一個InputStream對象)有一個read()方法可以讓您讀取數據。有一個問題:它讀取字節,而不是字符。只使用英文字母很無聊,所以讓我們嘗試從鍵盤上讀取漢字“魚”(只需從此處複製該字母並使用 PC 上的 ctrl + v或Mac 上的Command + v將其粘貼到控制台)。順便說一下,這個字符的意思是“魚”。控制台輸出: 233 173 154 10 這個符號和許多其他中文在計算機內存中佔用 3 個字節(不像拉丁字母,只佔用 1 個字節)。在這種情況下,從流中讀取 4 個字節:前三個字節表示字符“魚”,其他字節表示換行符(Enter)。因此,System.in以其樸素的形式不是我們的選擇。人類(極少數例外!)不知道如何讀取字節。但是 InputStreamReader班級來拯救!讓我們看看這是什麼動物。

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
我們傳遞System.inInputStreamReader對象。類名說明了一切!我們創建一個InputStreamReader對象並向它傳遞一個輸入流,它將從中讀取數據。在這種情況下...

new InputStreamReader(System.in)
...我們告訴它,“你將從系統輸入流(從鍵盤)中讀取數據”。但這不是它的唯一功能!不僅InputStreamReader從流中接收數據。它還將字節流轉換為字符流。換句話說,您不再需要將數據從“一和零”轉換為“人類可讀的語言”。InputStreamreader為你做一切。當然,InputStreamReader不限於從控制台讀取數據。它也可以從其他地方讀取數據。例如,從一個文件:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
在這裡,我們創建一個FileInputStream(一種風格的InputStream),傳入文件路徑,並將流本身傳遞給InputStreamReader. 現在它將能夠從文件中讀取數據(當然,如果文件實際存在於路徑中)。我們還使用InputStreamReader類的read()方法來讀取數據(數據的來源並不重要:控制台、文件或其他地方)。System.in.read()和有什麼區別InputStreamReader.read()?\ 讓我們再試著讀讀帶有 . 的字符“魚” InputStreamReaderSystem.in.read()我讓您想起: 233 173 154 10實際閱讀的內容 以及它們如何InputStreamReader做同樣的工作?

public class Main {

   public static void main(String[] args) throws IOException {

       InputStreamReader reader = new InputStreamReader(System.in);
       while (true) {
           int x = reader.read();
           System.out.println(x);
       }
   }
}
控制台輸出: 39770 10 差異立即顯現。最後一個字節(代表新行)保持不變(數字 10),但字符“魚”被轉換為單個代碼“39770”。這就是讀字的意思!如果你不相信 39770 代表字母“魚”,很容易說服自己:)
import java.io.IOException;

public class Main {

   public static void main(String[] args) throws IOException {

       char x = 39770;
       System.out.println(x);
   }
}
控制台輸出: 但是如果InputStreamReader這麼好,為什麼我們還需要BufferedReaderInputStreamReader知道如何讀取數據並將字節轉換為字符。我們還能要求什麼?為什麼是另一個讀者?:/ 答案很簡單:為了更好的性能便利性。讓我們從性能開始。當BufferedReader讀取數據時,它使用一個稱為緩衝區的特殊區域,在那裡它“存儲”它讀取的字符。最終,當程序中需要這些字符時,它們將從緩衝區中取出,而不是直接從數據源(鍵盤、文件等)中取出。這樣可以節省很多資源。 要了解其工作原理,請想像一家大公司的快遞員。快遞員坐在辦公室裡,等著有人送包裹。每次他收到一個新包裹,他就可以立即上路。但是白天可能會有很多包裹。他將不得不在辦公室和送貨地址之間進行多次往返。相反,快遞員在他的辦公室裡放了一個盒子。每個人都把他們的包裹放進箱子裡。現在,快遞員可以從容地拿著箱子從一個地址搬到另一個地址。這節省了很多時間,因為他不必每次都回到辦公室。在這個例子中,盒子只是一個緩衝區,office 是一個數據源。快遞員在送貨時從一個盒子裡取包裹比每次都回到辦公室要容易得多。他也會節省汽油。同樣,在程序中,從緩衝區中獲取數據比每次都引用數據源佔用的資源要少得多。因此,BufferedReader+比單獨InputStreamReader使用更快InputStreamReader。我們考慮了性能。方便呢?主要優點是Bufferedreader一次不僅可以讀取一個字符(儘管它可以用它的read()方法做到這一點),而且可以一次讀取整行!這是使用readLine()方法完成的;

public class Main {

   public static void main(String[] args) throws IOException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String s = reader.readLine();
       System.out.println("We read this line from the keyboard:");
       System.out.println(s);
   }
}
控制台輸出: CodeGym是學習Java最好的網站! 我們從鍵盤上讀到這行:CodeGym 是學習 Java 的最佳網站! 這在讀取大量數據時特別有用。一個字一個字地讀一兩行文本還是可行的。但是在《戰爭與和平》中一次讀一個字母會有些問題 :)

更多閱讀: