如何将System.out的输出重定向到JavaFx TextArea

huangapple go评论30阅读模式
英文:

How to redirect output from System.out to JavaFx TextArea

问题

我正在尝试创建一个简单的应用程序,允许我将所有的 System.out 重定向到 JavaFX 的 TextArea 中。

为此,我从 OutputStream 类创建了一个名为 CustomOutputStream 的类。以下是该类的代码:

//包名

//导入语句

public class CustomOutputStream extends OutputStream {
    private TextArea terminal;

    public CustomOutputStream(TextArea terminal) {
        this.terminal = terminal;
    }

    @Override
    public void write(int b) throws IOException {
        terminal.setText(terminal.getText() + String.valueOf((char) b));
    }
}

在我的 AppController.java 文件中,我将 TextArea 声明为 protected,以便我可以从同一包中的另一个类中访问它:

@FXML
protected static TextArea textArea_terminal;

现在,在 AppController.java 中,当按下一个按钮时,会调用另一个类中的一个函数(runShell())。这个函数(runShell())会调用 Channel 类的另一个函数,我希望将该函数的输出放入 TextArea 中。因此,我通过以下方式实现了我的 CustomOutputStream

PrintStream printStream = new PrintStream(new CustomOutputStream(AppController.textArea_terminal));
System.setOut(printStream);

channel.setOutputStream(System.out); // channel 是我需要输出的类的实例。

然而,尽管如此,在 TextArea 中和 IDE 终端中都没有输出。当我添加 System.out.println("hello") 来测试 printStream 时,出现了 NullPointerException

我认为可能是我传递 TextArea 变量的方式存在问题,或者可能是由于 channel 中的函数占用了线程造成的问题。

有关导致这种情况的原因以及如何解决它的任何想法吗?

英文:

I'm trying to create a simple app that allows me to redirect all System.out to a JavaFX TextArea within my app.

For this, I created a CustomOutputStream class from the OutputStream class. Here's the code for it:

//package name

//imports

public class CustomOutputStream extends OutputStream {
    private TextArea terminal;

    public CustomOutputStream(TextArea terminal) {
        this.terminal = terminal;
    }

    @Override
    public void write(int b) throws IOException {
        terminal.setText(terminal.getText() + String.valueOf((char) b));
    }
}

In my AppController.java file, I put TextArea as protected so I can access it from another class in the same package:

@FXML
protected static TextArea textArea_terminal;

Now this AppContoller.java, at the press of a button calls a function (runShell()) from another class. This function (runShell()) is the function that invokes another function of the Channel class whose output I'm hoping to put in the TextArea. As such, for this I implemented my CustomOutputStream this way:

PrintStream printStream = new PrintStream(new CustomOutputStream(AppController.textArea_terminal)) ;
System.setOut(printStream);

channel.setOutputStream(System.out); //channel is an instance of my class whose output I need.

Unfortunately, despite this, there is no output in the TextArea nor in the IDE terminal. And when I added System.out.println("hello") to test the printStream, a NullPointerException occured.

I'm thinking either there's an issue with the way I pass the TextArea variable or perhaps an issue with the thread being occupied by my function in channel.

Any ideas why is this caused and how to resolve it?

答案1

得分: 0

我明白我的问题非常具体,也许我的问题过于宽泛,无法充分传达这一点。

我的目标是从JSch库中exec函数的输出中获取System.err消息,并将其显示在JavaFX的TextArea中。因此,我需要从远程服务器获取错误流,而不是获取本地程序的错误流。

我尝试创建一个OutputStream来实现这一点,但并没有解决我的问题。因此,我想出了一个解决方法:

首先,我将JSch通道(我在其中运行exec函数)的错误写入文件中:

File file = new File("tempOut/errorLog.txt");
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
System.setErr(ps);
((ChannelExec) channel).setErrStream(System.err);

然后,我读取该文件并在GUI中显示其内容:

FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
            
String line;
while ((line = br.readLine()) != null)
{ 
    terminalOut = textArea_terminalOut.getText();
    terminalOut = terminalOut + "\n\n" + line;
}

这基本上是我为此问题找到的解决方法。如果有更好的方法,我仍然会很感激。

英文:

I understand my issue is of a very specific nature and my question was perhaps too broad to convey that sufficiently.

My objective was to get the System.err messages from the output of the exec function in the JSch library and display it in a JavaFX TextArea. As such, I needed to get the error stream from a remote server, not the error stream of my local program.

I attempted to create an OutputStream to perform this but it didn't solve my issue. As such, I figured out a workaround:

First I wrote the errors from the JSch channel (within which I run my exec fucntion) to a file:

File file = new File("tempOut/errorLog.txt");
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
System.setErr(ps);
((ChannelExec) channel).setErrStream(System.err);

Then I read that file and display its contents in my GUI:

FileReader fileReader = new FileReader(file);    
BufferedReader br = new BufferedReader(fileReader);  //creates a buffering character input stream  
            
String line;
while ((line = br.readLine()) != null)
{ 
    terminalOut = textArea_terminalOut.getText();
    terminalOut = terminalOut + "\n\n" + line;
}

And that's basically the workaround I figured out for this. If there's a better way, I'd still appreciate it.

huangapple
  • 本文由 发表于 2020年10月9日 16:02:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/64276170.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定