激凹みから立ち直る方法

外部コマンドを使用しない標準出力の取得方法を教えて下さい

いつもお世話になっています。
javaのプログラム内で、その直前の標準出力を取得する方法がわかりません。「標準出力 取得」などで検索しても、外部プロセスがらみ(Runtime.getRuntime().exec(xxx)のprocessからストリームを取得など)の事ばかりがヒットしてしまいます。
やりたい事はもっと単純で、標準出力をするメソッドを呼び出した後に、そのメソッドが標準出力した内容を取得したいのです。
以下のコードのコメントの箇所の、具体的な実装方法を知りたいのです。この例では簡単のために、標準出力するメソッドを同一クラス内のメソッドとしていますが、本当は別のクラスのメソッドで、もちろん標準出力の内容は実行時までわかりません。

public class hello {
  public static void main (String[] args) {

    sub();

    // sub()で標準出力した内容をここで取得したい!

  }

  private static void sub(){
    System.out.println("Hello World !!");
  }
}

A 回答 (6件)

単純に考えると


  static String logc = null;//キャッシュ用変数
  private static void sub(){
    logc = "Hello World !!";
    System.out.println(logc);
  }

こうしてあげれば
  public static void main (String[] args) {
    sub();
    // sub()で標準出力した内容をここで取得したい!
    // logcから取得できる
  }
となるのは分かるかしら?

System.out.printlnの記述が一箇所にまとまっていれば
こんなやり方もOKよね。

でもあっちこっちにある場合は
System.out.printlnの内部で
System.out.printlnとキャッシュ処理を用意してあげなくちゃダメね。


たとえばMyPrintStreamというPrintStreamクラスを継承したクラスを作成して
println(引数)メソッド内で
super.println(引数);
logc=引数;
をしてあげる。
あとはMyPrintStreamにget直前ログメソッドを作って
logcをリターンしてあげればいいわ。

この回答への補足

お礼が遅くなって、どうもすみません。それから再度のご登場、どうもありがとうございます。教えていただいた方法でコーディングして確認しようとしておりますが、コンパイルが通らなかったりランタイムエラーが出たりで、てこずっております…。(お礼欄に書かずに補足欄に書いてるのは、お礼欄に追記できないからです。)

補足日時:2010/06/05 14:39
    • good
    • 0
この回答へのお礼

しょうもない間違いをたくさんしつつ、ようやく動きました…。少しだけ、継承の利用方法がわかりました。本当にありがとうございました。

お礼日時:2010/06/05 16:08

世の中には TeePrintStream なんてものを作ってる人もいます.

    • good
    • 0
この回答へのお礼

いつもお礼が遅くなり、申し訳ありません。何度もご登場いただいて、本当にありがとうございます。TeePrintStreamを調べてみました。今後に応用できそうです、どうもありがとうございました。

お礼日時:2010/06/07 20:25

まず確認だけど, 「標準出力」というのは「System.out への出力」と思っていい? あと, ひょっとして「標準出力に出るはずだったものを取得する」だけじゃなくって「標準出力に出しつつ, その内容を取得する」ってこと?


いずれにしても, 原理的には可能です. 「2つの PrintStream に同時に出力する」ものが必要なんだけど, これくらいのことは当然考える人はいるようで, 調べればでてくる. それさえあれば, setOut で System.out を変更すればいいだけ.
    • good
    • 0
この回答へのお礼

お礼が遅くなり、申し訳ありません。ご回答どうもありがとうございました。

>まず確認だけど, 「標準出力」というのは「System.out への出力」と思っていい?
具体的には、コンソール画面への出力という意味です。Windowsでは、cmd.exeをたたいた時に出る黒い画面のことです。

>あと, ひょっとして「標準出力に出るはずだったものを取得する」だけじゃなくって「標準出力に出しつつ, その内容を取得する」ってこと?
はい。そのひょっとしてです。想定は、Javaプログラムから、コンソールに結果を出力するAPIをたたいた後、その出力結果を取り出して次の処理に使うという使い方です。そのAPIは単なるライブラリなので、Runtime.execとかを使うんじゃないんですよ…。

でも、原理的に可能とおっしゃっていただいて、安心しました。ちょっと調べ方が甘いようでまだ見つけられていませんが、やっぱりキーはsetOutなんですね。
どうもありがとうございました。

お礼日時:2010/06/05 13:47

 Bruce Eckel, "Thinking in Java (4th Edition)" (Prentice Hall, 2006)


によると、p.942~p.943に、次のようにあります。

 The Java System class allows you to redirect the standard input, output, and error I/O streams using simple static method calls:

 setIn(InputStream)
 setOut(PrintStream)
 setErr(PrintStream)

 Redirecting output is especially useful if you suddenly start creating a large amount of output on your screen, and it’s scrolling past faster than you can read it.
 Redirecting input is valuable for a command-line program in which you want to test a particular user-input sequence repeatedly.
 Here’s a simple example that shows the use of these methods:

//: c12:Redirecting.java
// Demonstrates standard I/O redirection.

import java.io.*;

public class Redirecting {
// Throw exceptions to console:
public static void main(String[] args)
throws IOException {
PrintStream console = System.out;
BufferedInputStream in = new BufferedInputStream(
new FileInputStream("Redirecting.java"));
PrintStream out = new PrintStream(
new BufferedOutputStream(
new FileOutputStream("test.out")));
System.setIn(in);
System.setOut(out);
System.setErr(out);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String s;
while((s = br.readLine()) != null)
System.out.println(s);
out.close(); // Remember this!
System.setOut(console);
}
}
    • good
    • 0
この回答へのお礼

ご丁寧なご回答、どうもありがとうございます。例示下さったコードのように、自由に標準入出力先を変えられるということは理解できました。この例のinという入力ファイルストリーム(っていうんでしょうか)をデフォルトの標準出力に変えて、outという出力ファイルストリームをオンメモリの文字列に書き出してやれば、できるということなんでしょうか。(情けないことに、今はそのように書き換えるスキルはありませんが…)

ただ、以下の2点がよくわかりません。javaの初心者には超難問に感じています。
1.標準出力先として、従来のコンソールに加えて別のバッファ(Stringとかを想定)も設定できたとして、それを別クラスのメソッドにどうやって伝えればよいのか?引数などで与えてやればできるのか?
2.別クラスのメソッドは、やはり本来のコンソール等に出力することが前提で、そのメソッドをコールした次のステートメントで「1つ前のステートメントで出した標準出力だけを取り込みたい」ということはできるのか?#2の方の仰るように、不可能なのか?別クラスのメソッド内でテンポラリファイルにもこっそり出力し、テンポラリファイルを読み込むというような方法でしか無理なのか?

とりとめの無い内容で申し訳ありませんが、どなたかもうしばらくお付き合いいただけるとうれしいです。

お礼日時:2010/06/04 00:27

無理ね。


保持していないし。

どうしてもやりたいのなら
自分で保持する仕組みを用意するしかないわ。
    • good
    • 0
この回答へのお礼

ご回答どうもありがとうございました。自分で保持する仕組みというのは、#1の方へのお礼に書いたようなことを自分でゴリゴリ実装するしかないということでしょうか。標準出力に出すものを前もって保存するような仕組み…情けないですが、まったく分かりません…。

お礼日時:2010/06/03 23:56

へ~, setOut なんてあるんだ....

    • good
    • 0
この回答へのお礼

早速のご回答、ありがとうございます。お礼が遅くなり、申し訳ありません。
教えて下さったのは、System.setOutのことなんですよね。API仕様には、標準出力ストリームの再割り当てと書かれていますね。恥ずかしながら、javaはまだ始めて間も無いので、今具体的に「こうすればいい」というのがわからないのですが、理論上は「できる」ということなんでしょうか。ただ、別クラスのメソッドに、「標準出力先はコンソールだけど、オンメモリでも保存しておいて」という指令が出せるものなのでしょうか?的外れなことを言っていますでしょうか。

お礼日時:2010/06/03 23:52

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報