【问题标题】:Capture the output of an external program in JAVA在 JAVA 中捕获外部程序的输出
【发布时间】:2013-01-10 15:14:53
【问题描述】:

我正在尝试使用 java 捕获外部程序的输出,但我不能。

我有代码可以显示它,但没有将它放入变量中。

例如,我将使用 sqlplus 来执行我的 oracle 代码“进入 exec.sql” system/orcl@orcl : 用户名/密码/数据库名

public static String test_script () {
        String RESULT="";
        String fileName = "@src\\exec.sql";
        String sqlPath = ".";
        String arg1="system/orcl@orcl";
        String sqlCmd = "sqlplus";


        String arg2   = fileName;
        try {
            String line;
            ProcessBuilder pb = new ProcessBuilder(sqlCmd, arg1, arg2);
            Map<String, String> env = pb.environment();
            env.put("VAR1", arg1);
            env.put("VAR2", arg2);
            pb.directory(new File(sqlPath));
            pb.redirectErrorStream(true);
            Process p = pb.start();
          BufferedReader bri = new BufferedReader
            (new InputStreamReader(p.getInputStream()));

          while ((line = bri.readLine()) != null) {

              RESULT+=line;

          }


          System.out.println("Done.");
        }
        catch (Exception err) {
          err.printStackTrace();
        }
 return RESULT;
    }

【问题讨论】:

  • 你问的不清楚。用System.out.println(line);可以看到,但是RESULT是空的?
  • RESULT一开始是空的,但是在while循环中我做了串联 --> RESULT+=line;
  • 好的,但是你能看到印有System.out.println(line); 的行吗?另请注意,由于您已重定向错误流,因此不需要 bre - 所有内容都将流式传输到 bri
  • 您不应该从外部程序的输出流中读取吗? p.getOutputStream()
  • 我纠正了错误

标签: java exec output


【解决方案1】:

由于进程将在新线程中执行,当您进入 while 循环时,可能没有输出或输出不完整。

Process p = pb.start();  
// process runs in another thread parallel to this one

BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));

// bri may be empty or incomplete.
while ((line = bri.readLine()) != null) {
    RESULT+=line;
}

因此,您需要等待该过程完成,然后再尝试与其输出交互。尝试使用Process.waitFor() 方法暂停当前线程,直到您的进程有机会完成。

Process p = pb.start();  
p.waitFor();  // wait for process to finish then continue.

BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));

while ((line = bri.readLine()) != null) {
    RESULT+=line;
}

这只是一种简单的方法,您还可以在进程并行运行时处理进程的输出,但是您需要监控进程的状态,即它是否仍在运行或是否已完成,以及输出的可用性.

【讨论】:

    【解决方案2】:

    使用Apache Commons Exec,它会让您的生活更轻松。查看tutorials 了解有关基本用法的信息。要在获得executor 对象(可能是DefaultExecutor)后读取命令行输出,请为您希望的任何流创建OutputStream(即FileOutputStream 实例可能是,或System.out),并且:

    executor.setStreamHandler(new PumpStreamHandler(yourOutputStream));
    

    【讨论】:

    • 这是一个java库。相信我,它会为您节省很多精力。如果您遇到任何问题,请在此处发布,我很乐意随时为您提供帮助:)
    • 10xxxxxxxxxxxxxxxxxxxx 我现在要测试它:D
    • @AHmédNet,很高兴认识兄弟 :) 它会为你省去很多麻烦 inshaa Allah
    • 我很困惑 - 它是否将 stdout 和 stderr 都写入同一个泵流处理程序?
    • 啊是的,有多个参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多