你好!今天的講座將分為兩個部分。我們將重複一些之前已經討論過的舊主題,並研究一些新功能:) 讓我們從第一個開始。重複是學習之母:) 你已經使用過這樣的類別了
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);
}
}
}
如果我們運行這段程式碼並在控制台中輸入字母“Y”,輸出將如下所示:
Й
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);
}
}
}
如果我們在控制台中輸入相同的字母“Y”,這次的結果將會不同:
Й
1049
10
InputStreamReader
將讀取的兩個位元組(208、153)轉換為單一數字 1049。這是按字元讀取。1049對應的是字母“Y”,很容易驗證:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
控制台輸出:
Й
好吧,對於BufferedReader
'a(以及一般情況下的 BufferedAnything),緩衝類別用於優化性能。就效能而言,存取資料來源(檔案、控制台、Internet 上的資源)是一項相當昂貴的操作。因此,為了減少此類呼叫的次數,BufferedReader
它會讀取資料並將其累積在一個特殊的緩衝區中,以便我們稍後可以從該緩衝區中接收資料。這樣一來,資料來源的呼叫次數就減少了幾倍甚至幾十倍!BufferedReader
'a的另一個附加功能及其相對於常規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("Пользователь ввел следующий текст:");
System.out.println(s);
reader.close();
}
}
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
Пользователь ввел следующий текст:
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
當然,BufferedReader
這是一種非常靈活的機制,讓您不僅可以使用鍵盤進行工作。例如,您可以直接從 Internet 讀取數據,只需將所需的 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"));
/*Сохраним текущее meaning System.out в отдельную переменную, чтобы потом
можно было переключиться обратно на вывод в консоль*/
PrintStream console = System.out;
// Присваиваем System.out новое meaning
System.setOut(filePrintStream);
System.out.println("Эта строка будет записана в текстовый файл");
// Возвращаем System.out старое meaning
System.setOut(console);
System.out.println("А эта строка - в консоль!");
}
}
結果,第一行將寫入文字文件,第二行將輸出到控制台:) 您可以將此程式碼複製到 IDE 並運行它。透過開啟文字文件,您將看到所需的行已成功寫入其中:) 講座結束。今天,我們記住瞭如何使用串流和讀者,回顧了它們之間的差異,並了解了System.out
我們幾乎每節課都使用的新功能:) 下一堂課見!
GO TO FULL VERSION