1

我创建了一个类,它可以动态编译、加载到 CustomClassLoader 中,并通过调用它的方法来执行内存中的java 源(即:没有类文件)java 源。main

我需要捕获StdOutStdInStdErr,尽管在我当前的代码中不可能这样做。( 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的覆盖stdoutstderr一个InputStreamfor stdin

就个人而言,我不喜欢简单地丢弃原始流,因为我倾向于只想重定向或解析它,而不是停止它(尽管你也可以这样做)。

这是这个想法的一个简单例子......

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 回答