<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] <!-- Appendix: Standard I/O --> # 附錄:標準IO >*標準 I/O*這個術語參考Unix中的概念,指程序所使用的單一信息流(這種思想在大多數操作系統中,也有相似形式的實現)。 程序的所有輸入都可以來自于*標準輸入*,其所有輸出都可以流向*標準輸出*,并且其所有錯誤信息均可以發送到*標準錯誤*。*標準 I/O* 的意義在于程序之間可以很容易地連接起來,一個程序的標準輸出可以作為另一個程序的標準輸入。這是一個非常強大的工具。 ## 從標準輸入中讀取 遵循標準 I/O 模型,Java 提供了標準輸入流 `System.in`、標準輸出流 `System.out` 和標準錯誤流 `System.err`。在本書中,你已經了解到如何使用 `System.out`將數據寫到標準輸出。 `System.out` 已經預先包裝[^1]成了 `PrintStream` 對象。標準錯誤流 `System.err` 也預先包裝為 `PrintStream` 對象,但是標準輸入流 `System.in` 是原生的沒有經過包裝的 `InputStream`。這意味著盡管可以直接使用標準輸出流 `System.out` 和標準錯誤流 `System.err`,但是在讀取 `System.in` 之前必須先對其進行包裝。 我們通常一次一行地讀取輸入。為了實現這個功能,將 `System.in` 包裝成 `BufferedReader` 來使用,這要求我們用 `InputStreamReader` 把 `System.in` 轉換[^2]成 `Reader` 。下面這個例子將鍵入的每一行顯示出來: ```java // standardio/Echo.java // How to read from standard input import java.io.*; import onjava.TimedAbort; public class Echo { public static void main(String[] args) { TimedAbort abort = new TimedAbort(2); new BufferedReader( new InputStreamReader(System.in)) .lines() .peek(ln -> abort.restart()) .forEach(System.out::println); // Ctrl-Z or two seconds inactivity // terminates the program } } ``` `BufferedReader` 提供了 `lines()` 方法,返回類型是 `Stream<String>` 。這顯示出流模型的的靈活性:僅使用標準輸入就能很好地工作。 `peek()` 方法重啟 `TimeAbort`,只要保證至少每隔兩秒有輸入就能夠使程序保持開啟狀態。 ## 將`System.out` 轉換成 `PrintWriter` `System.out` 是一個 `PrintStream`,而 `PrintStream` 是一個`OutputStream`。 `PrintWriter` 有一個把 `OutputStream` 作為參數的構造器。因此,如果你需要的話,可以使用這個構造器把 `System.out` 轉換成 `PrintWriter` 。 ```java // standardio/ChangeSystemOut.java // Turn System.out into a PrintWriter import java.io.*; public class ChangeSystemOut { public static void main(String[] args) { PrintWriter out = new PrintWriter(System.out, true); out.println("Hello, world"); } } ``` 輸出結果: ``` Hello, world ``` 要使用 `PrintWriter` 帶有兩個參數的構造器,并設置第二個參數為 `true`,從而使能自動刷新到輸出緩沖區的功能;否則,可能無法看到打印輸出。 ## 重定向標準 I/O Java的 `System` 類提供了簡單的 `static` 方法調用,從而能夠重定向標準輸入流、標準輸出流和標準錯誤流: - setIn(InputStream) - setOut(PrintStream) - setErr(PrintStream) 如果我們突然需要在顯示器上創建大量的輸出,而這些輸出滾動的速度太快以至于無法閱讀時,重定向輸出就顯得格外有用,可把輸出內容重定向到文件中供后續查看。對于我們想重復測試特定的用戶輸入序列的命令行程序來說,重定向輸入就很有價值。下例簡單演示了這些方法的使用: ```java // standardio/Redirecting.java // Demonstrates standard I/O redirection import java.io.*; public class Redirecting { public static void main(String[] args) { PrintStream console = System.out; try ( BufferedInputStream in = new BufferedInputStream( new FileInputStream("Redirecting.java")); PrintStream out = new PrintStream( new BufferedOutputStream( new FileOutputStream("Redirecting.txt"))) ) { System.setIn(in); System.setOut(out); System.setErr(out); new BufferedReader( new InputStreamReader(System.in)) .lines() .forEach(System.out::println); } catch (IOException e) { throw new RuntimeException(e); } finally { System.setOut(console); } } } ``` 該程序將文件中內容載入到標準輸入,并把標準輸出和標準錯誤重定向到另一個文件。它在程序的開始保存了最初對 `System.out` 對象的引用,并且在程序結束時將系統輸出恢復到了該對象上。 I/O重定向操作的是字節流而不是字符流,因此使用 `InputStream` 和 `OutputStream`,而不是 `Reader` 和 `Writer`。 <!-- Process Control --> ## 執行控制 你經常需要在Java內部直接執行操作系統的程序,并控制這些程序的輸入輸出,Java類庫提供了執行這些操作的類。 一項常見的任務是運行程序并將輸出結果發送到控制臺。本節包含了一個可以簡化此任務的實用工具。 在使用這個工具時可能會產生兩種類型的錯誤:導致異常的普通錯誤——對于這些錯誤我們只需要重新拋出一個 `RuntimeException` 即可,以及進程自身的執行過程中導致的錯誤——我們需要用單獨的異常來報告這些錯誤: ```java // onjava/OSExecuteException.java package onjava; public class OSExecuteException extends RuntimeException { public OSExecuteException(String why) { super(why); } } ``` 為了運行程序,我們需要傳遞給 `OSExecute.command()` 一個 `String command`,我們可以在控制臺鍵入同樣的指令運行程序。該命令傳遞給 `java.lang.ProcessBuilder` 的構造器(需要將其作為 `String` 對象的序列),然后啟動生成的 `ProcessBuilder` 對象。 ```java // onjava/OSExecute.java // Run an operating system command // and send the output to the console package onjava; import java.io.*; public class OSExecute { public static void command(String command) { boolean err = false; try { Process process = new ProcessBuilder( command.split(" ")).start(); try ( BufferedReader results = new BufferedReader( new InputStreamReader( process.getInputStream())); BufferedReader errors = new BufferedReader( new InputStreamReader( process.getErrorStream())) ) { results.lines() .forEach(System.out::println); err = errors.lines() .peek(System.err::println) .count() > 0; } } catch (IOException e) { throw new RuntimeException(e); } if (err) throw new OSExecuteException( "Errors executing " + command); } } ``` 為了捕獲在程序執行時產生的標準輸出流,我們可以調用 `getInputStream()`。這是因為 `InputStream` 是我們可以從中讀取信息的流。 這里這些行只是被打印了出來,但是你也可以從 `command()` 捕獲和返回它們。 該程序的錯誤被發送到了標準錯誤流,可以調用 `getErrorStream()` 捕獲。如果存在任何錯誤,它們都會被打印并且拋出 `OSExcuteException` ,以便調用程序處理這個問題。 下面是展示如何使用 `OSExecute` 的示例: ```java // standardio/OSExecuteDemo.java // Demonstrates standard I/O redirection // {javap -cp build/classes/main OSExecuteDemo} import onjava.*; public class OSExecuteDemo {} ``` 這里使用 `javap` 反編譯器(隨JDK發布)來反編譯程序,編譯結果: ``` Compiled from "OSExecuteDemo.java" public class OSExecuteDemo { public OSExecuteDemo(); } ``` [^1]: 譯者注:這里用到了**裝飾器模式**。 [^2]: 譯者注:這里用到了**適配器模式**。 <!-- 分頁 --> <div style="page-break-after: always;"></div>
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看