我想将一些字符串发送到子进程和它们,然后以大写形式发回给我。我的想法是,我把一个空字符串,两个过程都将停止。 第一次工作很好,但下一次这个过程第二次陷入困境,我需要强行关闭。
父亲代码 - >
public class padre {
public static void main(String[] args){
System.out.println("Soy el padre");
try {
Process p = Runtime.getRuntime().exec("java -jar C:\\Users\\Cristian\\Desktop\\hijo.jar");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader escritorPadre = new BufferedReader(isr);
//Leer del hijo
BufferedReader brHijo = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader brHijoError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//EScribir en el hijo
OutputStream os = p.getOutputStream();
String lineaConsola;
while((lineaConsola = escritorPadre.readLine()).isEmpty() == false){
lineaConsola +="\n";
os.write(lineaConsola.getBytes());
os.flush();
String linea;
while((linea = brHijo.readLine()) != null){
System.out.println(linea);
System.out.println("Atascado en el while del padre");
}
while((linea = brHijoError.readLine()) != null){
System.out.println(linea);
System.out.println("Atascado en el while del padre error");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
子代码 - >
public class hijo {
public static void main(String[] args){
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(in);
String linea;
try {
while(!(linea = br.readLine()).isEmpty()){
System.out.println("Hijo -> " + linea.toUpperCase()+"\n");
System.out.println("Atascado en el while del hijo");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
这里有几个问题。
首先,在主循环(父亲和儿子)中,您没有检查文件结尾。这意味着您可以从流阅读器获取null
,当您尝试访问NullPointerException
时,您将获得isEmpty()
。
其次,您永远不会将空行传递给子进程,因为只要从escritorPadre.readLine()
获得的行为空,就会退出while
循环。所以检查isEmpty()
的儿子是徒劳的。最好在退出后立即关闭子流(无论如何,当你完成它们时总是要关闭流),并处理儿子方面的null
。
但最重要的是:你从儿子那里读取的循环总是会卡住,因为你只能在流的末尾从儿子那边得到null
。如果儿子在其输出流(或儿子终止)上使用close()
,您将只获得流末尾。但如果你在儿子方面使用了close()
,那么你将无法再次写入标准输出。
所以你的循环只是等待儿子写别的东西,而儿子正在等待父亲在写东西之前写下别的东西。所以这个过程处于僵局。
您可以决定儿子应该发送一些特殊输出(空行),以便您知道何时停止读取其输出。
但是你有标准错误的问题。从儿子的输出读完后,你开始从标准错误中读取。因此,为了允许您离开该循环,您还必须在每次写入输出后将空行打印到标准错误,并且还向每个catch
打印的堆栈跟踪添加空行。然后你还必须在父亲的循环中添加一个空行检查,读取儿子的标准错误。
我个人认为这不是很优雅。但它是可行的。
无论如何,为了让你开始,在父亲那边,你应该确保关闭所有的流并在阅读时检查是否为空。类似的东西:
try {
p = Runtime.getRuntime().exec("java -jar C:\\Users\\Cristian\\Desktop\\hijo.jar");
} catch ( IOException e ) {
e.printStackTrace();
return;
}
// Use try-with-resources to open all the streams and readers
// so that they will be closed automatically
try (
BufferedReader escritorPadre = new BufferedReader(new InputStreamReader(System.in));
//Leer del hijo
BufferedReader brHijo = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader brHijoError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//EScribir en el hijo
OutputStream os = p.getOutputStream();
) {
String lineaConsola;
// Read until either end-of-file or empty line
while((lineaConsola = escritorPadre.readLine()) != null && ! lineaConsola.isEmpty()){
... // I ommitted the reading from the son until you decide how you want to arrange it.
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
在儿子中,同时确保关闭所有资源或使用try-with-resources,并检查null和空行:
try (
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
){
while((linea = br.readLine()) != null && ! linea.isEmpty()){
System.out.println("Hijo -> " + linea.toUpperCase()+"\n");
System.out.println("Atascado en el while del hijo");
// Decide how you want to handle telling the father that output is done
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}