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,这里值得一提的有两点

  1. Platform.runLater 这个方法会将传入的函数放入一个队列,用于更新ui,最开始我没有用这个方法结果导致控制台输出时界面时常卡死,如果不在这里用这个方法也可以选择用Task线程替代,在Task线程中控制台输出也可更新ui,但这里我又踩了个坑,用Task线程时调用System.out.println可以正常work,但调用System.out.print(char)的时候却没效果,应该是流没有及时flush的问题,不过我懒得追究了
  2. 这里把字符串的构建放到了runLater外面,一开始放在闭包里面结果输出到控制台的字节不对,部分能正常输出但部分会乱码,推测是byte[] b传入后又被更改了,所以这里要提前构建好字符串。

以上就已经实现了把System.outSystem.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.outSystem.err同理

posted @ 2018-12-11 17:57  世界知名伟人  阅读(1902)  评论(0编辑  收藏  举报