你好!為了方便起見,今天的課程將分為兩部分。我們將重複我們之前觸及的一些舊主題,並且我們將考慮一些新功能 :) 讓我們從第一個開始。你已經上過很多次課了
BufferedReader
。我希望你沒有時間忘記這句話:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
在進一步閱讀之前,試著記住每個組件 — System.in
, InputStreamReader
, BufferedReader
— 負責什麼以及為什麼需要它。你是否記得?如果沒有,不用擔心。:) 如果您忘記了什麼,請重新閱讀本課程,該課程專供讀者上課。我們將簡要回顧一下他們每個人可以做什麼。 System.in
— 這是一個從鍵盤接收數據的流。 原則上,它本身就足以實現閱讀文本所需的邏輯。但是,您會記得,System.in
只能讀取字節,不能讀取字符:
public class Main {
public static void main(String[] args) throws IOException {
while (true) {
int x = System.in.read();
System.out.println(x);
}
}
}
如果我們執行這段代碼並輸入西里爾字母“Й”,輸出將是:
Й
208
153
10
西里爾字符在內存中佔2個字節,顯示在屏幕上。數字 10 是換行符的十進製表示,即來自按 Enter 鍵。讀字節是一種樂趣,所以使用起來System.in
不是很方便。為了正確閱讀西里爾(和其他)字母,我們使用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);
}
}
}
我們輸入相同的字母“Й”,但這次結果不同:
Й
1049
10
InputStreamReader
將兩個字節(208和153)轉換為單個數字1049。這就是讀取字符的意思。1049對應西里爾字母“Й”。我們可以很容易地說服自己這是真的:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
控制台輸出:
Й
作為forBufferedReader
(一般而言BufferedAnythingYouWant
),緩衝類用於優化性能。訪問數據源(文件、控制台、Web 資源)在性能方面非常昂貴。因此,為了減少訪問次數,BufferedReader
將數據讀取並累積在一個專門的緩衝區中,我們從那裡獲取。結果,數據源被訪問的次數大幅減少——可能減少了幾個數量級!的另一個BufferedReader
特點及其優於普通的方法InputStreamReader
是非常有用的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 ("The user entered the following text:");
System.out.println(s);
reader.close();
}
}
BufferedReader+InputStreamReader is faster than InputStreamReader alone
The user entered the following text:
BufferedReader+InputStreamReader is faster than InputStreamReader alone
當然BufferedReader
是很靈活的。您不僅限於使用鍵盤。例如,您可以直接從 Web 讀取數據,只需將所需的 URL 傳遞給讀取器即可:
public class URLReader {
public static void main(String[] args) throws Exception {
URL oracle = new URL("https://www.oracle.com/index.html");
BufferedReader in = new BufferedReader(
new InputStreamReader(oracle.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
您可以通過傳遞文件路徑從文件中讀取數據:
public class Main {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("testFile.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream));
String str;
while ((str = reader.readLine()) != null) {
System.out.println (str);
}
reader.close();
}
}
替換 System.out
現在讓我們來看看我們以前沒有接觸過的一個有趣的功能。您一定記得,該類System
有兩個靜態字段 —System.in
和 System.out
. 這些孿生兄弟是流對象。 System.in
是一個InputStream
。並且System.out
是一個PrintStream
. 現在,我們將討論 System.out
. 如果我們進入System
類的源代碼,我們會看到:
public final class System {
……………...
public final static PrintStream out = null;
…………
}
因此, System.out
只是該類的一個普通靜態變量System
。這沒什麼神奇的:)out
變量是一個PrintStream
引用。這裡有一個有趣的問題:什麼時候System.out.println()
執行,為什麼輸出到控制台而不是其他地方?這可以以某種方式改變嗎?例如,假設我們要從控制台讀取數據並將其寫入文本文件。是否有可能以某種方式簡單地使用 System.out
而不是額外的閱讀器和編寫器類來實現這一點?的確,它是 :) 即使System.out
變量標有修飾符,我們也可以做到final
! 那麼我們需要什麼來實現這一點?首先,我們需要一個新PrintStream
對象來替換當前對象。當前對象,設置在System
默認情況下,類不符合我們的目的:它指向控制台。您需要創建一個指向文本文件的新文件——我們數據的“目的地”。其次,我們需要了解如何為變量分配新值System.out
。您不能使用簡單的賦值運算符,因為變量被標記為final
。 讓我們從頭開始倒推。碰巧的是,這個System
類有我們需要的方法:setOut()
。它獲取一個PrintStream
對象並將其設置為輸出目標。這正是我們所需要的!剩下的就是創建一個PrintStream
對象。這也很容易:
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
完整代碼如下所示:
public class SystemRedirectService {
public static void main(String arr[]) throws FileNotFoundException
{
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
/* Save the current value of System.out in a separate variable so that later
we can switch back to console output */
PrintStream console = System.out;
// Assign a new value to System.out
System.setOut(filePrintStream);
System.out.println("This line will be written to the text file");
// Restore the old value of System.out
System.setOut(console);
System.out.println("But this line will be output to the console!");
}
}
結果,第一個字符串被寫入文本文件,第二個字符串顯示在控制台中 :) 您可以將這段代碼複製到您的 IDE 中並運行它。打開文本文件,你會看到字符串已經成功寫入:) 到此,我們的課程就結束了。今天我們回顧瞭如何使用流和閱讀器。我們回顧了它們之間的不同之處,並了解了 的一些新功能System.out
,我們幾乎在每節課中都使用了這些功能 :) 直到下一節課!
GO TO FULL VERSION