【问题标题】:How can I unblock from a Java started process?如何解除对 Java 启动进程的阻止?
【发布时间】:2009-04-16 10:38:16
【问题描述】:

当从 cmd 行执行某些命令(比如说“x”)时,我收到以下消息: “....按任意键继续 。 。 。”。所以它等待用户输入解除阻塞。

但是当我从 java 执行相同的命令('x')时:

Process p = Runtime.getRuntime().exec(cmd, null, cmdDir);
// here it blocks and cannot use outputstream to write somnething
p.getOutputStream().write(..);

代码块...

我试图在进程的输出流中写入一些东西,但是我怎么能这样做,因为代码永远不会到达那一行?

【问题讨论】:

    标签: java process


    【解决方案1】:

    我认为(虽然不能确定)您说的是 Windows 而不是 Unix?

    如果是这样,那么命令行进程可能实际上并没有等待stdin 上的按键(或输入),而是执行与旧 DOS kbhit() 功能等效的操作。

    AFAIK 没有办法让该功能相信键盘已被按下而没有实际按下键。

    为了测试这个理论,创建一个包含一些空行的文本文件“input.txt”,然后运行:

    foo.exe < input.txt
    

    这将显示您的程序是在等待 stdin 还是在其他东西上。

    【讨论】:

      【解决方案2】:

      您应该同时读取子进程的输出流和错误流。这些流的缓冲区大小是有限的。如果其中一个缓冲区已满,则子进程将阻塞。我认为这就是你的情况。

      【讨论】:

        【解决方案3】:

        我认为在 Java 中执行外部应用程序的推荐方法是使用 ProcessBuilder。代码看起来像

        //Launch the program
        ArrayList<String> command = new ArrayList<String>();
        command.add(_program);
        command.add(param1);
        ...
        command.add(param1);
        
        ProcessBuilder builder = new ProcessBuilder(command);
        //Redirect error stream to output stream
        builder.redirectErrorStream(true);
        
        Process process = null;
        BufferedReader br = null;
        try{
            process = builder.start();
        
            InputStream is = process.getInputStream();
            br = new BufferedReader( new InputStreamReader(is));
            String line;
        
            while ((line = br.readLine()) != null) {
                 log.add(line);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally{
            try{
                br.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        

        流程对象有一个 get[Input/Output/Error]Stream 可用于与程序交互。

        【讨论】:

          【解决方案4】:

          程序无法继续,因为它在等待用户输入时被阻止。

          一种选择是在单独的线程中启动外部进程,或者使用共享进程 p 的线程以便能够写入其流。

          【讨论】:

            【解决方案5】:

            我在this stackoverflow question写了一个命令行执行的答案。

            您的问题有点棘手,因为您可能需要回复。

            在你的情况下,我可能需要给输入流 gobbler 提供类似回复通道的东西:

             StreamGobbler outputGobbler = new StreamGobbler(
                                                proc.getInputStream(), "OUTPUT", 
                                                proc.getOutputStream());
            

            并使其匹配模式并回复给定的输入流。

            while ((line = br.readLine()) != null) {
                System.out.println(type + ">" + line);
                if (line.contains(PRESS_KEY_CONTINUE) {
                    ostream.write("y".getBytes("US-ASCII")); 
                    System.out.println("< y"); 
                }
            }
            

            希望这会有所帮助。

            【讨论】:

              【解决方案6】:

              所以这是我对这个问题的解决方法,灵感来自 Alnitak 的建议: 像这样运行命令:

              Process p = Runtime.getRuntime().exec(cmd + " < c:\\someTextFile.txt", null, cmdDir);
              ...
              int errCode = p.waitFor();
              ...
              

              “someTextFile.txt”可以通过编程方式创建到临时目录中,然后删除。

              【讨论】:

                【解决方案7】:

                使用 PrintWriter 模拟一些输入:

                        Process p = Runtime.getRuntime().exec(cmd, null, cmdDir);
                        //consume the proces's input stream
                        ........
                        // deblock
                        OutputStream outputStream = p.getOutputStream();
                        PrintWriter pw = new PrintWriter(outputStream);
                        pw.write("ok");
                        pw.flush();
                        int errCode = p.waitFor();
                

                【讨论】:

                  【解决方案8】:

                  我遇到了同样的问题,我找到了解决方案。它不是最优雅的,但它确实有效。

                  1 - 当您执行流程时,您会从流程中获取 inputStream 2 - 然后你循环接收提示中显示的消息,如果有的话 3 - 当你看到你从“提示”得到“按一个键继续”或其他什么时,你结束进程

                              // Creates the runtime and calls the command
                          Process proc = Runtime.getRuntime().exec(Destino);
                  
                          // Get the proccess inputStream
                          InputStream ips = proc.getInputStream();
                          String output = "";
                  
                          int c = 0;
                  
                          // Read the output of the pro
                          while ((c = ips.read()) != -1
                                  && !output.contains("Press any key to continue")) {
                              output = output + (char)c;
                          }
                  
                          // Destroy the proccess when you get the desired message
                          proc.destroy();
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2011-01-08
                    • 2018-09-30
                    • 2018-03-30
                    • 2016-10-31
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-09-28
                    相关资源
                    最近更新 更多