未重定向Java System.out

未重定向Java System.out,java,io,stream,Java,Io,Stream,我有一个捕获所有系统输出的简单任务;然而,我没有做到: public class Main { ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); ArrayList<String> history = new ArrayList<>(); StringBuilder output = new StringBuilder(); StringBuilde

我有一个捕获所有
系统输出的简单任务;然而,我没有做到:

public class Main {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
    ArrayList<String> history = new ArrayList<>();
    StringBuilder output = new StringBuilder();
    StringBuilder input = new StringBuilder();
    JPanel panel = new JPanel();
    JTextArea txt = new JTextArea();
    String PROMPT = "> ";
    Runnable show = new Runnable() {
            public void run() {
                txt.setText("");
                for (String line: history) txt.append(line + "\n");
                txt.append(PROMPT);
                txt.append(output.toString());
                txt.setCaretPosition(txt.getText().length());
            }
        };
    PrintStream os = new PrintStream(new OutputStream() {
            @Override
            public void write(int b) throws IOException {
                if (b == 13) {
                    history.add(input.toString());
                    input = new StringBuilder();
                    SwingUtilities.invokeLater(show);
                } else input.append((char)b);
            }
        });
    void init(String title) {
        panel.setLayout(new BorderLayout());
        txt.setLineWrap(true);
        txt.setFont(new Font("Courier", Font.PLAIN, 16));
        txt.setBackground(Color.BLACK);
        txt.setForeground(Color.GREEN);
        txt.setCaretColor(Color.GREEN);
        txt.setEditable(false);
        txt.setText(PROMPT);
        txt.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
                if (e.getKeyChar() == '\n') {
                    System.setOut(os);
                    System.setErr(os);
                    String result = output.toString();
                    history.add(PROMPT + result);
                    try {
                        engine.eval(result);
                    } catch (ScriptException ex) {
                        history.add(ex.toString());
                    }
                    output = new StringBuilder();
                } else {
                    output.append(e.getKeyChar());
                }
                SwingUtilities.invokeLater(show);
            }
            @Override
            public void keyPressed(KeyEvent e) {

            }
            @Override
            public void keyReleased(KeyEvent e) {

            }
        });
        panel.add(txt, BorderLayout.CENTER);
        JFrame frame = new JFrame(title);
        frame.setSize(650, 425);
        frame.setContentPane(panel);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    public static void main(String args[]) {
        new Main().init("javascript");
    }
}

除了正常的
STDOUT
a.k.a.
System.out
外,输出不在任何地方。为什么?

脚本引擎输出重定向:

要重定向脚本的输出,首先必须获取其ScriptContext实例,该实例有一个名为setWriter(Writer)的方法。 这将设置脚本引擎的输出

为此,你首先需要一个作家。这可以像下面这样简单:

public class CaptureWriter extends Writer
{

    private StringBuilder m_build;

    public CaptureWriter(StringBuilder build)
    {
        m_build = build;
    }

    @Override
    public void write(char[] cbuf, int off, int len) throws IOException
    {
        m_build.insert(m_build.length(), cbuf, off, len);
    }

    @Override
    public void flush() throws IOException
    {
    }

    @Override
    public void close() throws IOException
    {
    }

}
这会将所有输入写入StringBuilder

然后将其注册到脚本上下文中

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");

engine.getContext().setWriter(new CaptureWriter(m_mess));
运行此简单程序时:

StringBuilder build = new StringBuilder();

    ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");

    engine.getContext().setWriter(new CaptureWriter(build));

    try
    {
        engine.eval("print(\"Hello\")");
        engine.eval("print(\"World\")");
        engine.eval("print(\"You\")");
        engine.eval("print(\"There\")");
    } catch(ScriptException e)
    {
        e.printStackTrace();
    }

    System.out.println(build);
输出是脚本的缓冲输出:

Hello
World
You
There
当然,您可以将任何内容挂接到Writer实现的write方法中,这只是一个示例

System.out重定向:

要捕获System.out输出,您必须制作自己的PrintStream实现,它可以非常简单,如:

public class Capture extends PrintStream
{

    private StringBuilder m_build;

    public Capture(OutputStream out, StringBuilder build)
    {
        super(out);

        m_build = build;
    }

    public void println(String s)
    {
        super.println(s);

        m_build.append(s + "\n");
    }

}
然后您需要在运行时注册它:

StringBuilder build = new StringBuilder();

System.setOut(new Capture(System.out, build));
然后每次调用System.out.println时,它都会像覆盖的PrintStream一样工作,并将消息写入提供的StringBuilder中


要捕获其他消息,您需要覆盖其他方法。

您可以捕获System.out,它将提供一个由您控制的打印流。。。试试这样的

ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
PrintStream old = System.out;
System.setOut(ps);
System.out.println("This will be captured :P");
System.out.flush();
System.setOut(old);
System.out.println("He is what was captured : " + baos.toString());

问题的哪一部分没有解决?它捕获System.out输出并允许您使用它做任何事情。我在获取
ScriptEngine
输出的问题中描述的问题添加了有关如何重定向脚本输出的信息,很快将添加代码片段。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
PrintStream old = System.out;
System.setOut(ps);
System.out.println("This will be captured :P");
System.out.flush();
System.setOut(old);
System.out.println("He is what was captured : " + baos.toString());