2010-05-20 82 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讀入文件。