【问题标题】:How to extract inputStream before process finishes如何在流程完成之前提取 inputStream
【发布时间】:2012-05-15 07:10:52
【问题描述】:

我需要在启动后提取进程的输入流。 今天我可以获得初始信息,但是在我关闭应用程序之前该方法不会返回(在这种情况下,应用程序由进程启动:gedit 和 firefox)。我的意思是,我知道它会在我关闭进程后返回,但我想有一个解决方法来在进程关闭之前得到它。 请参阅下面的代码。

public class ProcessInvokerExtractingProcessInformation {

    public static void main(String args[]) {



        try {
            Process pOpenApp = new ProcessBuilder(new String[] { "gedit",
                    "/home/thais/Documents/gedit_doc1" }).start();

            printInformation("pOpenApp", pOpenApp);

            // * just for testing error message and input stream
            Process openFirefox = new ProcessBuilder(new String[] { "firefox" })
                    .start();
            printInformation("lsInstruction", openFirefox);


            deleteProcess(pOpenApp);
            deleteProcess(openFirefox);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }




    // method for testing information we can see regarding the process
    public static void printInformation(String id, final Process process) {

        System.out.println(" Process " + id + ":");

                    //tried to run in a separated thread but didn't work as well
            Runnable r = new Runnable(){
            public void run(){
                System.out.print("\n        Process error message -> ");
            printScannedStream(process.getErrorStream());
            System.out.println("\n        Process input message -> ");
            printScannedStream(process.getInputStream());
            }

            };

            Thread a = new Thread(r);
            a.start();



            /* other approaches to print the streams, tried before
                StringWriter writer = new StringWriter();

            try {
              PrintWriter pWriter = new PrintWriter(new
              BufferedOutputStream(process.getOutputStream()));
              pWriter.write("Hi"); pWriter.flush(); System.out.println(
              " Process output stream is for writing so there is no information "
              );
             *//*
            InputStreamReader isr = new InputStreamReader(
                    process.getErrorStream());
            BufferedReader br = new BufferedReader(isr);
            System.out.print("\n        Process error message -> ");
            while (br.readLine() != null) {
                System.out.print(br.readLine());
            }
            System.out.println("\n        Process input message -> ");

            isr = new InputStreamReader(process.getInputStream());
            br = new BufferedReader(isr);
            while (br.readLine() != null) {
                System.out.print(br.readLine());
            }

            br.close();
            isr.close();*/
            /*
             * IOUtils.copy(process.getErrorStream(), writer, null);
             * System.out.println("        Process error message -> " +
             * writer.toString());
             * 
             * IOUtils.copy(process.getInputStream(), writer, null);
             * System.out.println("        Process input stream message -> " +
             * writer.toString()+"\n");

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
*/
    }

    /**
     * Method that close all streams and after destroy the process It's
     * important to close the streams to avoid file descriptions leaking
     * 
     * @param process
     */
    public static void deleteProcess(Process process) {
        try {
            process.getInputStream().close();
            process.getOutputStream().close();
            process.getErrorStream().close();
            process.destroy();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }



    public static void printScannedStream(java.io.InputStream is) {
        try {
            Scanner scanner = new Scanner(is);
            while(scanner.hasNext()) {
                System.out.print(scanner.next());

            }

        } catch (java.util.NoSuchElementException e) {
            e.printStackTrace();
        }


    }

}

【问题讨论】:

    标签: java process


    【解决方案1】:

    我遇到了同样的问题,我用一个额外的线程解决了它。

    class InputHandler implements Runnable {
    
        InputStream input_;
    
        InputHandler(InputStream input) {
            input_ = input;
        }
    
        public void run() {
            try {
                int c;
                String line = "";
                while ((c = input_.read()) != -1) {
                 if (((char) c == '\r') || ((char) c == '\n')) {
                 if (!line.isEmpty()) flushString(line);
                 line = "";
                 } else
                 line += (char) c;
                }
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    
        private void flushString(String s) {
         // any code to process data from stream
         Logger.debug("library: " + getClass().getName() + ": compress: output: " + s);
        }
    
    }
    
    
    
    
    Process process = run.exec(ffmpegCmdString);
    // read output
    InputHandler stderrHandler = new InputHandler(process.getErrorStream());
    new Thread(stderrHandler).start();
    InputHandler stdoutHandler = new InputHandler(process.getInputStream());
    new Thread(stdoutHandler).start();
    process.waitFor();
    

    【讨论】:

    • 您好 Nikolay,非常感谢您的关注。我试过你的代码,但实际上它和我的一样。我的意思是,它会在我关闭进程之前打印进程信息,但程序仍在等待进程完成以继续。我想要一些不会停止应用程序的东西。我的意思是,它会打印,如果有东西要打印,然后会定期继续应用程序。你认为这可能吗?
    • 嗨 Nikolay,实际上现在你的代码对我来说很完美。我只需要删除 waitFor(),因为我将该方法用于多个进程。
    • 而且,与我的代码相比,我注意到逻辑相似。我的错误是我试图在同一个运行线程中查看 errorStream 和 inputStream 。创建两个线程,每个流一个,解决了这个问题。再次,非常感谢!
    • 哦,是的,真的。你绝对是对的。我没有意识到您在代码中提到了线程。无论如何,我很高兴能为您提供一种找到解决方案的新方法:-)。欢迎。
    猜你喜欢
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 2012-03-10
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 2015-07-14
    相关资源
    最近更新 更多