如何将 STDIO 重定向到 java 应用程序上的 GUI 组件?
在 CI 上,我会简单地创建几个管道并使用 dup2 覆盖 std 文件描述符,而在另一端,我会利用阻塞 IO 在无限循环上为每个输出管道(sdtout、sdterr)创建一个线程管道来更新适合控制台建议的文本区域/画布。至于标准输入,我会监听此类组件上的关键事件,并将它们写入管道。
但是如何在 Java 上使用 swing 来执行此操作呢?
我无法将本机代码混合为项目指令。到目前为止,我已经破坏了许多项目指令,所以我无法继续下去......
此外,提供某种级别的终端仿真(例如 VT100)会很酷,但是如何在 unix 上通知 java 应用程序这种功能我会设置 TERM envvar。
在 CI 上会执行以下操作:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static pthread_t workers[2];
static void *_worker(void *file)
{
int c;
if(!file) pthread_exit(NULL);
while((c=fgetc(file))!=EOF) {
// Sync and put C on the screen
}
pthread_exit(NULL);
}
int initConsole()
{
int stdin_pipe[2], stdout_pipe[2], stderr_pipe[2];
if(!(pipe(stdin_pipe)||pipe(stdout_pipe)||pipe(stderr_pipe))) {
if(dup2(stdin_pipe[0], STDIN_FILENO)<0) return -1;
if(dup2(stdout_pipe[1], STDOUT_FILENO)<0) return -1;
if(dup2(stderr_pipe[1], STDERR_FILENO)<0) return -1;
pthread_create(&workers[0], NULL, _worker, fdopen(stdout_pipe[0], "r"));
pthread_create(&workers[1], NULL, _worker, fdopen(stderr_pipe[0], "r"));
// Register a handler within the toolkit to push chars into the stdin_pipe
return 0;
}
return -1;
}
On C I would simple create a couple of pipes and use dup2 to overwrite the std file descriptor, while on the other end I'd create a thread for each outputing pipes (sdtout, sdterr) on a infinite loop taking advantage of the blocking IO of pipes to updated the textArea/canvas fitting the propose of a console. As for the stdin, I would listen for key events on such component, writing those to the pipe.
But how can I perform that on Java with swing?
I can't mix native code as a project directive. I already broke many project directives so far, so I can't push on that...
Also it would be cool to provide some level of terminal emulation, such as VT100, but how to inform the java app of such capability, on unix I would set the TERM envvar.
On C I would do the following:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static pthread_t workers[2];
static void *_worker(void *file)
{
int c;
if(!file) pthread_exit(NULL);
while((c=fgetc(file))!=EOF) {
// Sync and put C on the screen
}
pthread_exit(NULL);
}
int initConsole()
{
int stdin_pipe[2], stdout_pipe[2], stderr_pipe[2];
if(!(pipe(stdin_pipe)||pipe(stdout_pipe)||pipe(stderr_pipe))) {
if(dup2(stdin_pipe[0], STDIN_FILENO)<0) return -1;
if(dup2(stdout_pipe[1], STDOUT_FILENO)<0) return -1;
if(dup2(stderr_pipe[1], STDERR_FILENO)<0) return -1;
pthread_create(&workers[0], NULL, _worker, fdopen(stdout_pipe[0], "r"));
pthread_create(&workers[1], NULL, _worker, fdopen(stderr_pipe[0], "r"));
// Register a handler within the toolkit to push chars into the stdin_pipe
return 0;
}
return -1;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以通过子类化 PrintStream 并将您的类简单地写入 JTextArea,将 System.out 定向到 JTextArea。然后简单地创建类的实例并调用 System.setOut(yourInstance);
您可以通过子类化 InputStream 并通过从 JTextArea 返回数据来实现
read()
方法,对 System.in 执行非常类似的操作。You can direct System.out to a JTextArea by subclassing PrintStream and getting your class to simply write to the JTextArea. Then simple create an instance of your class and call
System.setOut(yourInstance)
;You can do a pretty similar thing with System.in by subclassing InputStream and implementing the
read()
method by returning data from the JTextArea.System.err/out 和 in 在 java 中应该做同样的事情。另外,您继承了通道 [System.inheritedChanne()]
我一开始就误解了您的问题,所以如果您需要在线程中读取 System.in 并使用 EventQueue.invokeLater() 附加到文本区域中。
System.err/out and in should do the same in java. Also you have inherited channel [System.inheritedChanne()]
I misunderstood your question at 1st, so if you need to just read System.in in a thread and use EventQueue.invokeLater() to append into a text area.