2010-05-20 84 views
7

我试图从Java代码执行程序。这里是我的代码:从Java执行外部程序

public static void main(String argv[]) { 
    try { 
     String line; 
     Process p = Runtime.getRuntime().exec(
      "/bin/bash -c ls > OutputFileNames.txt"); 
     BufferedReader input = new BufferedReader(
      new InputStreamReader(p.getInputStream())); 
     while ((line = input.readLine()) != null) { 
     System.out.println(line); 
     } 
     input.close(); 
    } catch (Exception err) { 
     err.printStackTrace(); 
    } 
} 

我的操作系统是Mac OS X 10.6。

如果我从getRuntime().exec()方法中删除"> OutputFileNames.txt",则所有文件名都会打印在控制台上。但我需要将它打印到文件中。

另外,如果我改变了命令:

Process p = Runtime.getRuntime().exec(
    "cmd \c dir > OutputFileNames.txt"); 

,并在Windows上运行它,它运行并打印文件中的结果完全正常了。

我已经阅读了其他文章来执行Java的另一个应用程序,但似乎没有涉及到我的问题。

我真的很感谢任何帮助,我可以得到。

感谢,

+0

如果你想要做的唯一的事情是列出目录中的文件,那么没有理由通过外部程序来做到这一点 - 你可以使用'File.listFiles()'并将结果写入文件中。这将适用于任何操作系统,不需要特定于Mac OS X或Windows的代码。 – Jesper 2010-05-20 14:25:24

+0

这只是我正在尝试的一件基本事情。最终,我想要做的是运行一个外部程序调用并将该程序的输出打印到一个文件中,然后从Java解析文件来完成其他有用的工作。 – 2010-05-20 14:27:32

+1

您是否尝试过使用.exec(new String [] {“/ bin/bash”,“-c”,“ls> OutputFileNames.txt”});它也失败了吗? – Anton 2010-05-20 14:32:23

回答

8

得到尽可能写的,你需要做的这个重定向的工作:

Process p = Runtime.getRuntime().exec(
     new String[]{"/bin/bash", "-c", "ls > OutputFileNames.txt"}); 

你正在运行到的问题是头脑简单的方式,即Runtime.exec(String)拆分命令换成参数。因为“打击”的“-c”选项需要

$ /bin/bash -c "ls > OutputFileNames.txt" 

如果你运行一个命令(如为)在shell提示下,你将不得不进入它作为生成的shell的命令行作为单个shell参数。但是,如果您要将裸露的引号放入Java字符串中,那么Runtime.exec(String)方法仍然会导致分裂错误。唯一的解决方案是将命令参数作为数组提供。

+0

javadoc声明命令行被分割:“命令参数被解析为标记,然后作为独立进程中的命令执行。标记解析由StringTokenizer完成......”。请参阅http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#exec%28java.lang.String%29 new StringTokenizer(command) – mdma 2010-05-20 14:39:34

+0

@mdma - and这当然是问题所在。 StringTokenizer不理解带引号的字符串。 – 2010-05-20 14:50:11

+0

好吧,我看到你的编辑,你已经引用了bash命令。我没有注意到原来的命令行是错误的。 – mdma 2010-05-20 14:52:08

1

有几件事要看。

  • 检查程序运行在哪个目录(通过以相同方式运行pwd),然后检查以确保您有权写入该目录。
  • 看看文件OutputFileNames.txt是否已经存在(并检查权限)。
  • 如果文件确实存在,请删除它并重新运行以查看它是否被重新创建,并查看其中的内容。
  • 尝试使用命令"/bin/bash -c 'ls > OutputFileNames.txt'" - 这可能是bash输出一样ls输出(在你的榜样重定向可以适用于bash而非ls)。
1

问题正在发生,因为进程的标准输出正被定向到文件,所以java Process无法收集输出。

如果你想输出写入一个文件,并在Java读取可用,这时你有两种选择:

  1. 守在原地重定向,然后读取来自OutputFile.txt上市在Java中,例如使用new FileReader("OutputFile.txt")。请注意,exec()是异步的,并且在进程写入文件之前可以返回,因此您需要等待进程退出,方法是使用Process.waitFor()
  2. 删除重定向,并将列表直接读入java(如您所做的那样)。然后您可以使用FileWriter将此列表写入文件。

底线是你不能同时使用重定向和读取进程的输出 - 它是一个或另一个。

编辑:你的意见表明1)是首选的方法。这会将输出写入文件(使用OS shell),然后在进程退出时从java读入文件。