javaFX的控制台实现
最近做了个javaFX的工具,想弄个控制台输出信息,准备用TextArea来模拟console,但直接操纵console对象的话不依赖这个项目的地方就无法输出信息到控制台了,至于log,以前弄过一个输出到console,log文件,和TextArea的程序,但得出的结论是很多时候log和控制台的内容是不一样的,log和console的内容应该分开,最后决定用System.out,将TextArea定为标准输出流的target。
gui的部分略过,界面弄好后,首先要做的是定义一个OutputStream,这个stream会将数据写到textArea,也就是我们的console。
System.setOut(new PrintStream(new OutputStream() {
@Override
public void write(int b) {
String text = String.value0f((char) b);
Platform.runLater(() -> {
console.appendText(text);
});
}
@Override
public void write(byte[] b, int off, int len) {
String s = new String(b, off, len);
Platform. runLater(() -> console. appendText(s));
}
}, true));
System.setErr(System.out);
以上的console是一个TextArea,这里值得一提的有两点
Platform.runLater
这个方法会将传入的函数放入一个队列,用于更新ui,最开始我没有用这个方法结果导致控制台输出时界面时常卡死,如果不在这里用这个方法也可以选择用Task线程替代,在Task线程中控制台输出也可更新ui,但这里我又踩了个坑,用Task线程时调用System.out.println可以正常work,但调用System.out.print(char)的时候却没效果,应该是流没有及时flush的问题,不过我懒得追究了- 这里把字符串的构建放到了runLater外面,一开始放在闭包里面结果输出到控制台的字节不对,部分能正常输出但部分会乱码,推测是
byte[] b
传入后又被更改了,所以这里要提前构建好字符串。
以上就已经实现了把System.out
和System.err
输出到TextArea console
的功能了,接下来在记录下把cmd的信息输出到这里
Process process = Runtime.getRuntime.exec(...);// 这里执行cmd
Charset charset = Charset.forName("gbk");
new Thread(()->{
try(InputStreamReader reader = new InputStreamReader(process.getInputStream(), charset)){
int read;
while((read = reader.read()) != -1){
System.out.print((char)read);
}
} catch (IOException e){
e.printStackTrace();
}
}).start();
这里起了一个线程是为了防止界面卡死,异步将cmd的输出流输出到System.out
,这里的charset应当与cmd的编码一致,中文系统的cmd的编码是gbk
而java默认编码是utf-8
,所以需要创建一个gbk
的字节流再输出到console,这里只输出了System.out
,System.err
同理