JAVA - 在循环中将数据发送到子进程

时间:2014-12-07 20:58:14

标签: java process inputstream outputstream

我想将一些字符串发送到子进程和它们,然后以大写形式发回给我。我的想法是,我把一个空字符串,两个过程都将停止。 第一次工作很好,但下一次这个过程第二次陷入困境,我需要强行关闭。

父亲代码 - >

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();
    }
}

}

1 个答案:

答案 0 :(得分:0)

这里有几个问题。

  • 首先,在主循环(父亲和儿子)中,您没有检查文件结尾。这意味着您可以从流阅读器获取null,当您尝试访问NullPointerException时,您将获得isEmpty()

  • 其次,您永远不会将空行传递给子进程,因为只要从escritorPadre.readLine()获得的行为空,就会退出while循环。所以检查isEmpty()的儿子是徒劳的。最好在退出后立即关闭子流(无论如何,当你完成它们时总是要关闭流),并处理儿子方面的null

    < / LI>
  • 但最重要的是:你从儿子那里读取的循环总是会卡住,因为你只能在流的末尾从儿子那边得到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();
}