Java 可中断地读取子进程的输出
我想启动一个子进程并读取其输出,直到EOF或清除内部标志 我的第一次尝试是在另一个线程中调用Java 可中断地读取子进程的输出,java,process,pipe,Java,Process,Pipe,我想启动一个子进程并读取其输出,直到EOF或清除内部标志 我的第一次尝试是在另一个线程中调用InputStream.close(),但尽管它对套接字有效,但它对进程的结果不起作用。getInputStream():主线程仍在read()中等待,而killer线程要么挂起在close0()(windows)中,要么继续无效(linux) 然后我尝试检查InputStream.available(),但它没有检测到EOF:它返回0 public class BbbTest extends TestC
InputStream.close()
,但尽管它对套接字有效,但它对进程的结果不起作用。getInputStream()
:主线程仍在read()
中等待,而killer线程要么挂起在close0()
(windows)中,要么继续无效(linux)
然后我尝试检查InputStream.available()
,但它没有检测到EOF:它返回0
public class BbbTest extends TestCase {
private Process proc;
private InputStream getStream() throws IOException {
//if ("".length() == 0) return new java.net.Socket("intra", 80).getInputStream();
String[] cmd;
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
cmd = new String[] { "cmd", "/c", "more & more" };
} else {
cmd = new String[] { "sh", "-c", "cat; cat" };
}
Process proc = Runtime.getRuntime().exec(cmd);
return proc.getInputStream();
}
public void testB() throws Exception {
final InputStream in = getStream();
final Thread readingThread = Thread.currentThread();
Thread t = new Thread("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") {
@Override
public void run() {
try {
sleep(1000);
if (proc != null) proc.destroy(); // this won't help
readingThread.interrupt(); // this won't help either
in.close(); // this will do nothing and may even hang
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException ( );
}
}
};
t.setDaemon(true);
t.start();
try {
in.read();
assertTrue(false);
} catch (IOException e) {
// nothing
}
}
}
我最后的希望是从返回的流中窃取通道并在windows中使用nio,此命令不会终止
cmd = new String[] { "cmd", "/c", "more & more" };
不要尝试这个简单的命令
cmd = new String[] { "cmd", "/c", "dir" };
如果你想读你的流
public static void slurp(final InputStream is, final int bufferSize)
{
try(final Reader in = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(in);){
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
通过像这样传递流来调用此方法
final BbbTest bbTest = new BbbTest();
Thread t = new Thread("xsdfds") {
@Override
public void run() {
try {
slurp(bbTest.getStream());
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException ( );
}
}
};
t.start();
如果要从子线程终止进程。
在BbbTest中为流程创建setter和getter方法,如下所示
public class BbbTest {
private Process proc;
/**
* @return the proc
*/
public Process getProc() {
return proc;
}
/**
* @param proc the proc to set
*/
public void setProc(Process proc) {
this.proc = proc;
}
private InputStream getStream() throws IOException {
String[] cmd;
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
// cmd = new String[] { "cmd", "/c", "more & more" };
cmd = new String[] { "cmd", "/c", "dir" };
} else {
cmd = new String[] { "sh", "-c", "cat; cat" };
}
proc = Runtime.getRuntime().exec(cmd);
return proc.getInputStream();
}
}
现在,使用这个过程,您可以销毁
bbTest.getProc().destroy();
如果希望基于其他流的输出终止进程,可以通过检查行内容在slurp方法中添加逻辑,并使用destroy终止
UPDATE
简单演示
public class BbbTest {
private Process startProcess(String[] commands) throws IOException {
Process proc = Runtime.getRuntime().exec(commands);
return proc;
}
public static void slurp(final InputStream is)
{
try(final Reader in = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(in);){
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
if (line.equals("end")){
break;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
final BbbTest bbTest = new BbbTest();
final Process process = bbTest.startProcess(new String[] { "cmd", "/c", "more" });
Thread t = new Thread("xsdfds") {
@Override
public void run() {
try {
slurp(process.getInputStream());
process.destroy();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException ( );
}
}
};
t.start();
try(OutputStream out = process.getOutputStream();
BufferedOutputStream outStream = new BufferedOutputStream(out);){
outStream.write("Test".getBytes());
outStream.write("\n".getBytes());
outStream.write("end".getBytes());
outStream.write("\n".getBytes());
outStream.flush();
}
}
}
看看这个示例:您应该有一些条件来终止子线程(读取prcoess),比如流写入“end/”或EOF的end(process closed inputstream)您想要读取另一个进程在流中写入的内容,还是想要终止子线程process@Mani不幸的是,“我想启动一个子进程并读取其输出”那么为什么要尝试终止/关闭该流。并且您正在执行的命令不会自行终止它(more&more)@Mani这只是一个示例。我不介意它是否被终止,但主要目标是退出read(),请查看我的答案。如果您想读取,可以使用该命令进行读取。”在windows中,此命令不会终止。“-这就是问题所在!我不能接受您的答案,因为它无法停止从无法终止的进程中读取您的意思。您需要有条件停止(EOF-在您的情况下,它不是EOF)或者基于outputCheck我的最后一个注释。如果您不想等到EOF,那么您必须进行条件设置。例如,如果流写入结束/退出/终止,您应该销毁它不会杀死整个树,因此不会关闭它们的管道末端