Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Java运行交互式shell程序_Java_Exec - Fatal编程技术网

用Java运行交互式shell程序

用Java运行交互式shell程序,java,exec,Java,Exec,我正在尝试(但失败)解决如何在Java中运行一个完全交互式的shell程序 以下是场景: 我有一个大型GUI应用程序,它是跨平台的,用Java编写的。为此,我尝试添加一个用于运行headless的交互式命令行环境。事情的那一面都是美好的。但是,主GUI的功能之一是编辑文件。现在,对于命令行界面,我希望能够执行一个外部编辑器来编辑文件,然后在保存并退出后返回到原来的位置。例如,在Linux上,它可能执行“vi/path/to/file” 那么,如何执行该命令,使键盘和显示器与应用程序完全交互?我不

我正在尝试(但失败)解决如何在Java中运行一个完全交互式的shell程序

以下是场景:

我有一个大型GUI应用程序,它是跨平台的,用Java编写的。为此,我尝试添加一个用于运行headless的交互式命令行环境。事情的那一面都是美好的。但是,主GUI的功能之一是编辑文件。现在,对于命令行界面,我希望能够执行一个外部编辑器来编辑文件,然后在保存并退出后返回到原来的位置。例如,在Linux上,它可能执行“vi/path/to/file”

那么,如何执行该命令,使键盘和显示器与应用程序完全交互?我不想让它在后台运行。我不希望它通过Java重定向IO,我只希望一个命令“在前台”运行,直到它存在

就像我在C中使用了
system()
函数一样

到目前为止,我发现的所有东西都在后台运行命令,或者通过Java管道传输IO,这对于交互式(非行模式)应用程序是不起作用的

哦,还有最后一个警告:我仅限于Java1.6的兼容性,所以我无法使用
ProcessBuilder
做一些奇特的事情

以下是强制性SSCCE:

class exetest {
    public static void main(String[] args) { 
        try {
            Process p = Runtime.getRuntime().exec("vi");
            p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
我希望Runtime.getRuntime().exec()会一直阻塞,直到我在
vi
中完成为止,在这段时间内,所有键盘输入都会直接(
RAW
)到
vi
,所有屏幕输出都会直接返回给用户,不受影响

这就是我在C语言中实现它的方法:

void main() {
    system("vi");
}
更新:

这达到了预期的效果,但a)仅限于Linux/OSX(问题不大,但最好是跨平台),b)是一个可怕的难题:

import java.io.*;

class exetest {
    public static void main(String[] args) {
        try {
            Process p = Runtime.getRuntime().exec("/bin/bash");
            OutputStream stdin = p.getOutputStream();
            PrintWriter pw = new PrintWriter(stdin);
            pw.println("vi < /dev/tty > /dev/tty");
            pw.close();
            p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
import java.io.*;
类测试{
公共静态void main(字符串[]args){
试一试{
进程p=Runtime.getRuntime().exec(“/bin/bash”);
OutputStream stdin=p.getOutputStream();
PrintWriter pw=新的PrintWriter(标准输入法);
println(“vi/dev/tty”);
关闭();
p、 waitFor();
}捕获(例外e){
e、 printStackTrace();
}
}
}

首先,ProcessBuilder也在Java6中。如果你的意思是这个版本不充分,或者什么的,那么我想有两条信息你需要知道。首先,运行“外部编辑器”的主要方式可能是使用运行时类和exec方法。我怀疑你已经在做什么了?其次,您当前的GUI在某种程度上有一个“事件循环”,它是一个简单但主要的线程,只执行“等待事件”(如按键或“窗口事件”),将该事件分派给感兴趣的侦听器,然后等待下一个事件。按键和事件到外部编辑器,将不会通过此事件循环。。。无论如何,如果不使用更复杂的东西,比如OLE API,这并不容易。但是,正是“事件循环”让Java保持了活力和交互性,同时其他事情也在进行,比如在外部编辑器中编辑。我不确定您使用的是什么GUI框架,但大多数都已经有了这样的循环,您不必担心它。如果您是说在您想要的命令行模式下,您不希望正常的GUI运行,那么您基本上必须复制“事件循环”,首先启动该线程,然后调用runtime.exec方法。有道理吗

FWIW,如果您没有“源代码”来查看当前使用的GUI框架,如果您想查看一个,只是为了了解更多关于事件循环的信息,那么它的“显示”类中有一个,以及一些可能与您想要做的类似的示例。(注意,SWT可以“独立”运行,而不需要Eclipse的其余部分,以防您感到奇怪)


HTH

我事先声明,这是一个可怕的混乱局面,但考虑到你的限制,我不确定你会找到更优雅的东西

而且,它在Windows上也不起作用

使用bash:

class Exetest {
    public static void main(String[] args) { 
        try {
            // Create a one-liner for bash
            // Note that the trick is to do all the redirects and
            // give the name of the file in a single argument.
            String [] commandline = new String[3];
            commandline[0] = "bash";
            commandline[1] = "-c";
            commandline[2] = "vi </dev/tty >/dev/tty test.txt";
            Process p = Runtime.getRuntime().exec(commandline);
            p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
类测试{
公共静态void main(字符串[]args){
试一试{
//为bash创建一行程序
//注意,诀窍是执行所有重定向和
//在单个参数中指定文件名。
String[]命令行=新字符串[3];
命令行[0]=“bash”;
命令行[1]=“c”;
命令行[2]=“vi/dev/tty test.txt”;
进程p=Runtime.getRuntime().exec(命令行);
p、 waitFor();
}捕获(例外e){
e、 printStackTrace();
}
}
}

通过这种方式,您可以在运行时编写实际的命令。

系统(“vi”)
相当的精确的是:

final ProcessBuilder p = new ProcessBuilder("vi");
p.redirectInput(Redirect.INHERIT);
p.redirectOutput(Redirect.INHERIT);
p.redirectError(Redirect.INHERIT);

p.start().waitFor();

(我知道这要推迟3年,但对于其他有同样问题的人来说)

你想要类似的东西吗?不,我不想要。我不希望Java与执行的程序交互,我希望用户与它交互。因此,他们键入
edit myfile
,它执行
vi/path/to/myfile
,用户编辑文件就像他们在终端键入
vi/path/to/myfile
一样。在CLI模式下运行时,没有GUI。GUI代码甚至还没有开始。当它这样做的时候,一切都在摇摆。没有GUI,就没有GUI事件循环。实际上,我正在为CLI接口使用JLine。6中的ProcessBuilder没有重定向类。你说得对,这是一个可怕的难题;)是的,它实现了预期的结果,但我不确定我是否能够接受这种实现。编辑器可执行文件将在运行时决定,我不确定您能否在一行中创建一个bash命令,包括重定向,因此它必须动态生成一个脚本以供执行。