ホームページ >Java >&#&チュートリアル >ブロックを回避するために Java プロセスで入力/出力ストリームを適切に処理する方法

ブロックを回避するために Java プロセスで入力/出力ストリームを適切に処理する方法

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-17 18:00:16689ブラウズ

How to Properly Handle Input/Output Streams in Java Processes to Avoid Blocking?

入出力ストリームを使用した Java プロセス

次のコード スニペットを考えてみましょう。

Scanner scan = new Scanner(System.in);

Process process = Runtime.getRuntime().exec("/bin/bash");
OutputStream stdin = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdout = process.getInputStream();

BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));

String input = scan.nextLine();
input += "\n";
writer.write(input);
writer.flush();

input = scan.nextLine();
input += "\n";
writer.write(input);
writer.flush();

while ((line = reader.readLine()) != null) {
    System.out.println("Stdout: " + line);
}

input = scan.nextLine();
input += "\n";
writer.write(input);
writer.close();

while ((line = reader.readLine()) != null) {
    System.out.println("Stdout: " + line);
}

このコードにより、次のことが可能になります。 bash シェルにコマンドを入力し、その出力を受け取ります。ただし、最初の入力と出力の後、その後の入力では予期した出力が得られません。

この問題が発生する理由

この問題は、コードが正しく処理されないために発生します。 bash プロセスの標準出力のファイルの終わり (EOF) 条件。ループ while ((line = Reader.readLine()) != null) は、プロセスが終了した場合にのみ終了します。つまり、プロセスからの出力がそれ以上ない場合、ループは無期限にブロックされます。

提案された解決策 - ProcessBuilder と --EOF-- の処理

この問題に対処するには、次の点を考慮してください。変更:

ProcessBuilder builder = new ProcessBuilder("/bin/bash");
builder.redirectErrorStream(true);
Process process = builder.start();

Runtime.getRuntime().exec() の代わりに ProcessBuilder を使用すると、bash プロセスの標準エラーを標準出力にリダイレクトでき、必要な入力ストリームは 1 つだけになります。

さらに、特別な区切り文字 --EOF-- を送信して、コマンドからの出力の終了を知らせるようにコードを変更できます。これにより、コードで複数のコマンドから出力を確実に分離できるようになります。

while (scan.hasNext()) {
    String input = scan.nextLine();
    if (input.trim().equals("exit")) {
        // Putting 'exit' amongst the echo --EOF--s below doesn't work.
        writer.write("exit\n");
    } else {
        writer.write("((" + input + ") & echo --EOF-- || echo --EOF--)\n");
    }
    writer.flush();

    line = reader.readLine();
    while (line != null && !line.trim().equals("--EOF--")) {
        System.out.println("Stdout: " + line);
        line = reader.readLine();
    }
}

これらの変更により、コードは複数のコマンドとその出力を確実に処理し、必要な機能を提供できるようになります。

以上がブロックを回避するために Java プロセスで入力/出力ストリームを適切に処理する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。