1

私は動的にコンパイルし、CustomClassLoader にロードし、そのメソッドを呼び出すことによってインメモリJava ソース (つまり、クラス ファイルなし) Java ソースを実行するクラスを作成しましたmain

StdOutStdIn、およびをキャプチャする必要がありますStdErrが、現在のコードでは実行できません。( Compiler API + Classloader + Reflection)

私の要件は、この質問で尋ねられたものと同じである可能性があり、受け入れられた回答で示唆されているように、java.lang.Processを使用してください。これは、ファイル システムで利用可能な物理ファイルがあれば簡単ですが、この場合はありません。

Classloader + Reflection戦略を削除し、代わりに提案を使用する予定です。ただし、 Process クラスを使用して実際にリダイレクトすることに慣れていません。Std*

Java 7でこれを行うにはどうすればよいですか? (スニペットは非常に高く評価されます) またはもっと重要なのは、より良いアプローチはありますか?

4

2 に答える 2

0
  • 既存の出力ストリームのバックアップを取ります。

PrintStream realSystemOut = System.out;

  • 他の出力ストリームに設定します [fileOutputStream、または他のいくつかのストリーム] PrintStream overridePrintStream = new PrintStream(new FileOutputStream("log.txt"));

    System.setOut(overridePrintStream);

    - - - 処理する - - -

  • 実際のストリームを System.out に戻します

    System.setOut(realSystemOut);

ありがとう

于 2013-09-17T20:48:49.667 に答える
0

Java では、独自のPrintStreamオーバーライドstdoutとfor をstderr指定できます。InputStreamstdin

個人的には、元のストリームを単純に破棄するのは好きではありません。リダイレクトまたは解析するだけで、停止したくない傾向があるためです (ただし、それを行うこともできます)。

これがアイデアの簡単な例です...

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

public class RedirectStdOut {

    public static void main(String[] args) {

        Consumer stdConsumer = new Consumer() {

            @Override
            public void processLine(StreamCapturer capturer, String text) {
            }

            @Override
            public void processCharacter(StreamCapturer capturer, char character) {
                capturer.getParent().print(character);
            }
        };

        StreamCapturer stdout = new StreamCapturer(stdConsumer, System.out);
        StreamCapturer stderr = new StreamCapturer(stdConsumer, System.err);

        System.setOut(new PrintStream(stdout));
        System.setErr(new PrintStream(stderr));

        System.out.println("This is a test");
        System.err.println("This is an err");

    }

    public static interface Consumer {

        public void processLine(StreamCapturer capturer, String text);

        public void processCharacter(StreamCapturer capturer, char character);
    }

    public static class StreamCapturer extends OutputStream {

        private StringBuilder buffer;
        private Consumer consumer;
        private PrintStream parent;
        private boolean echo = false;

        public StreamCapturer(Consumer consumer, PrintStream parent) {
            buffer = new StringBuilder(128);
            this.parent = parent;
            this.consumer = consumer;
        }

        public PrintStream getParent() {
            return parent;
        }

        public boolean shouldEcho() {
            return echo;
        }

        public void setEcho(boolean echo) {
            this.echo = echo;
        }

        @Override
        public void write(int b) throws IOException {
            char c = (char) b;
            String value = Character.toString(c);
            buffer.append(value);
            if (value.equals("\n")) {
                consumer.processLine(this, value);
                buffer.delete(0, buffer.length());
            }
            consumer.processCharacter(this, c);
            if (shouldEcho()) {
                parent.print(c);
            }
        }
    }

}

StreamCapturerは、必要に応じて出力をエコーする機能を備えていますConsumer。私は通常Consumer、ストリームを介して来るものを処理するために を使用します。必要に応じて、完全な行を待つか、個々の文字を処理できます...

于 2013-09-17T22:00:11.230 に答える