我正在尝试编写一个程序,该程序启动Windows控制台(cmd)的进程,并将Input,Output和Errorstream重定向到System.in/out/err。此外,如果进程已关闭(通过命令退出),我的程序应该关闭。
我已经写了一个解决方案。唯一的问题是我使用过的线程没有注意到进程被关闭了。此外,我不知道为所有这些流写一个新的线程是不是很好,所以如果你知道一个更容易的解决方案来重定向流,我想听听它。
这是我的SSCCE:
public class Main {
public static boolean run = true;
public static void main(String[] args) throws IOException {
ProcessBuilder p = new ProcessBuilder("cmd");
final Process pr = p.start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
pr.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test");
run = false;
}
});
// read(is);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(System.in, pr.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getInputStream(), System.out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("finish");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getErrorStream(), System.err);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
public static void write(InputStream is, OutputStream os)
throws IOException {
byte[] buf = new byte[1024];
int len = is.read(buf);
if (len != -1) {
byte[] data = new byte[len];
for (int i = 0; i < len; i++) {
data[i] = buf[i];
}
os.write(data);
os.flush();
}
}
}
会发生什么,是我为流的每个重定向创建一个新的Thread,重定向本身通过write(inputStream,outputStream)
方法发生。
但我用来检查进程是否已关闭(pr.waitFor()
)的线程并不像我想象的那样工作。因此,如果cmd关闭,我就不会被注意到。
EDIT2
好的,我只是忘了启动线程。但现在我能够接近这个问题了。
将System.in重定向到process.getOutputStream()并没有注意到该进程将被关闭。这是因为is.read(buf)
是一种阻止方法。因此,如果我尝试向Process写一个新命令,那么它会注意到流应该被关闭并完成程序。
如果有任何解决方案可以在没有线程的情况下重定向Streams,我希望以这种方式实现它。我认为这会更容易使用。
答案 0 :(得分:2)
主要问题是你在帖子上没有.start
,但我还想提出改进建议
等待主线程中的进程:
public class Main {
public static boolean run = true;
public static void main(String[] args) throws IOException {
ProcessBuilder p = new ProcessBuilder("cmd");
final Process pr = p.start();
// read(is);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(System.in, pr.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getInputStream(), System.out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("finish");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getErrorStream(), System.err);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
try {
pr.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test");
run = false;
}
public static void write(InputStream is, OutputStream os)
throws IOException {
byte[] buf = new byte[1024];
int len = is.read(buf);
if (len != -1) {
byte[] data = new byte[len];
for (int i = 0; i < len; i++) {
data[i] = buf[i];
}
os.write(data);
os.flush();
}
}
}
答案 1 :(得分:0)
我猜这是因为你的主线程可以在所有这些线程完成之前退出。尝试在主要功能的末尾添加pr.waitFor()
。