【问题标题】:A Java program that runs an external "java myprog < input.txt > output.txt"运行外部“java myprog < input.txt > output.txt”的Java程序
【发布时间】:2012-04-18 14:42:22
【问题描述】:

我想编写一个运行外部“java myprog output.txt”命令的Java 程序。最终目标是在两个不同的程序上运行此命令,并比较它们与各自输出文件的输出相似性。

我想我已经阅读了几乎所有关于使用 ProcessBuilder 运行外部程序的相关文章,以及关于在该外部程序中处理用户输入的少数条目,但我仍然无法让事情正常工作。根据我的阅读,我认为最好的方法是不运行上面的确切命令,而是读取 input.txt 文件并将其逐字节输入 Process 对象,然后收集输出并将其写入输出.txt ...我对其他选项100%开放。

我根据我的阅读整理了下面的代码。它似乎正确地将 input.txt 中的输入输入到 myprog,但是当我尝试将外部程序的输出打印到控制台以进行验证时,程序挂起在 myprog 中预期(意外)用户输入的位置。

无论是否使用 redirectErrorStream(true) 行,我都会遇到相同的问题。

我真的希望这是用 Java 编写的,因为我计划与我将比较其程序输出的人共享源代码,而他们主要只熟悉 Java。

import java.io.*;
import java.util.*;

public class test7 {

    public static void main(String args[]) {

        try {
            // WANT: "java myprog < input.txt > output.txt"
            String inputFile = "input.txt";
            String outputFile = "output.txt";

            ProcessBuilder pb = new ProcessBuilder("java","myprog");
            pb.redirectErrorStream(true); // merge stdout, stderr of process
            Process p = pb.start();

            // write input to the running program
            OutputStream pos = p.getOutputStream();
            InputStream fis = new FileInputStream(inputFile);
            int read = 0;
            while ( (read = fis.read()) != -1) {
                pos.write(read);
            }
            fis.close();

            // get output of running program
            InputStreamReader isr = new  InputStreamReader(p.getInputStream());
            BufferedReader br = new BufferedReader(isr);

            // HANGS HERE WHEN USER INPUT REQUIRED
            String lineRead;
            while ((lineRead = br.readLine()) != null) {
                System.out.println(lineRead);
            }

        }
        catch (IOException e) {
            e.printStackTrace(); 
        }
    } // end main

}

这里是myprog.java的内容:

import java.io.*;

public class myprog {

    public static void main(String args[]) throws IOException {

        System.out.println("Hello world!");
        System.out.println("Enter something:");

        BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));

        // the readLine() command causes ProcessBuilder to hang
        cin.readLine();
    }   
}

而input.txt文件就是

p

output.txt 文件应该是

Hello world!
Enter something:

【问题讨论】:

  • 需要用户输入是什么意思?您能否展示您的 myprog 或至少展示其最相关的部分?此外,如果您在此处需要更好的帮助,请遵循 Java 命名约定。您使用非标准命名(包括不将类名的首字母大写)使您的代码混乱。
  • 我前段时间回答过这个问题。stackoverflow.com/questions/3062305/…
  • @HovercraftFullOfEels:我在描述中添加了 myprog.java 的内容。对于没有将班级名称大写,我深表歉意。
  • @dsmith:我使用命令“java myprog”和“java myprog
  • 您可能需要同时处理标准流。我会给气垫船代表。

标签: java user-input processbuilder external-process


【解决方案1】:

我想知道您的问题是否部分与不使用单独的线程来读取输入和写入输出有关。例如:

   public static void main(String args[]) {

      try {
         // WANT: "java myprog < input.txt > output.txt"
         String inputFile = "input.txt";
         String outputFile = "output.txt";

         // my ProcessBuilder Strings will be different from yours
         ProcessBuilder pb = new ProcessBuilder("java", "-cp", ".;bin;",
               "yr12.m04.a.MyProg");
         pb.redirectErrorStream(true); 
         Process p = pb.start();

         final OutputStream pos = p.getOutputStream();
         final PrintWriter pw = new PrintWriter(pos);
         final InputStream fis = new FileInputStream(inputFile);
         final BufferedReader fileBr = new BufferedReader(new InputStreamReader(fis));

         InputStreamReader isr = new InputStreamReader(p.getInputStream());
         final BufferedReader br = new BufferedReader(isr);

         new Thread(new Runnable() {
            public void run() {
               String lineRead;
               try {
                  while ((lineRead = br.readLine()) != null) {
                     System.out.println(lineRead);
                  }
               } catch (IOException e) {
                  e.printStackTrace();
               } finally {
                  if (br != null) {
                     try {
                        br.close();
                     } catch (IOException e) {
                        e.printStackTrace();
                     }
                  }
               }
            }
         }).start();

         new Thread(new Runnable() {
            public void run() {
               try {
                  String lineRead;
                  while ((lineRead = fileBr.readLine()) != null) {
                     pw.println(lineRead);
                  }
               } catch (IOException e) {
                  e.printStackTrace();
               } finally {
                  if (pw != null) {
                     pw.close();
                  }
                  if (fileBr != null) {
                     try {
                        fileBr.close();
                     } catch (IOException e) {
                        e.printStackTrace();
                     }
                  }
               }
            }
         }).start();

      } catch (IOException e) {
         e.printStackTrace();
      }
   } // end main

【讨论】:

  • 就是这样!与 java 命令中的类路径开关完美配合。非常感谢!!!!!!
【解决方案2】:

您是否考虑过使用 Runtime.getRuntime().exec() 代替?

Process proc = Runtime.getRuntime().exec("java myprog "+inputFile+" "+outputFile);

【讨论】:

  • 这与使用 ProcessBuilder 相比没有优势。
  • 我在我的示例中留下了“”,你添加了这些吗? @Hovercraft... 1 行代码与 10 行代码在我的书中始终是一个优势,但对每个人来说都是一个优势。
  • 是的,我在测试中添加了“”。
  • @user282172 - 我认为标准 io 重定向在 Java Process 对象中不起作用。至少他们不会在所有平台上。
  • 然后简单地编写一个调用java程序的包装批处理/shell程序,并让你的exec调用它传入和传出文件名。
【解决方案3】:

您可以包含“myprog”的 jar 并自己调用 main() 方法。更何况如果 myprog 在您的域中,您可以完全摆脱 main 方法。

【讨论】:

    猜你喜欢
    • 2014-09-12
    • 2013-08-27
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多