JavaFX:将控制台输出重定向到在JavaFX中创建的TextArea

一直对于控制台有个问题,他是如何捕获到println的内容?

思路:我们可以将,控制台的内容从他的父类容器中截获,使它的内容可以显示到我们想让他显示的地方去。

在控制台,system的out()方法一直在监控全局,system有个方法,system.setOut()是将监控的内容输出到指定地点,system.setErr()是将异常输出。这是主要的两个地点,通常情况下,在监控器打开的时候,会指定这两个地方,比如cmd会将这两个值设置为在cmd窗口下append()拼接。在eclipse中,会将这两个值指向console控制台。这个值是可以改变的。所以,我们可以用javafx写一demo,实现这个功能。

在Java中有个PrintSteram,这个有点像javafx中 的scene,只是一个容器,在printSteam中存放print()的内容,然后将它的内容铺写到指定的textArea中,这个文本框必须继承OutputStream类,实现他的write()方法,这里需要加一个监听,将printSteram的内容实时监控刷新,然后显示。

最后,附上代码。

main.java


import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("../demo3/test.fxml"));
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
            primaryStage.setTitle("控制台输出测试");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

MainController.java


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;

public class MainController {
    @FXML
    private TextArea console;
    private PrintStream ps;

    public void initialize() {
        ps = new ConsolePrint(console);
    }

    public void button(ActionEvent event) {
        System.setOut(ps);
        System.setErr(ps);
        System.out.println("你好世界");
        this.testIpConfig();

    }

    public void testIpConfig() {
        Runtime runtime = Runtime.getRuntime();
        try {
            runtime.exec("ipconfig");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Process process = null;
        try {
            process = runtime.exec("cmd.exe /c dir d:\\");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        InputStream inputStream = process.getInputStream();
        BufferedReader br = null;
        //cmd系统默认设置为gbk码,这里解析为gbk码
        br = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("GBK")));
        String line = null;
        try {
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public class ConsolePrint extends PrintStream {//可以正常解析utf8和gbk码
        TextArea console;

        public ConsolePrint(TextArea console) {
            super(new ByteArrayOutputStream());
            this.console = console;
        }

        @Override
        public void write(byte[] buf, int off, int len) {
            print(new String(buf, off, len));
        }

        @Override
        public void print(String s) {
            console.appendText(s);
        }
    }

    public class Console extends OutputStream {
        private TextArea console;

        public Console(TextArea console) {
            this.console = console;
        }

        public void appendText(String valueOf) {
            console.appendText(valueOf);
        }

        public void write(int b) throws IOException {
            appendText(String.valueOf((char) b));//这里解析非ascii码会出错乱码
        }
    }
}

test.fxml