2012-11-20 82 views
7

我一直在嘗試編寫一個java程序,它使用Runtime.getRuntime().exec()方法來使用命令行來運行程序「tesseract」的一個實例。如何獲得java getRuntime()。exec()來運行帶參數的命令行程序?

一些背景,Tesseract是一個免費的開源程序,用於在圖片上執行OCR(光學字符識別)。它需要一個圖片文件並輸出一個文本文件。它是使用此命令的命令行程序(從命令提示外殼內)運行

tesseract imageFilePath outFilePath [optional arguments] 

例如:

tesseract "C:\Program Files (x86)\Tesseract-OCR\doc\eurotext.tif" "C:\Users\Dreadnought\Documents\TestingFolder\out" 

第一個參數調用的tesseract程序,所述第二個是圖像文件的絕對路徑,最後一個參數是輸出文件的路徑和名稱。 Tesseract只需要輸出文件的名稱,它不需要擴展名。

從命令提示符工作,這工作完美。然而,我想從一個Java程序運行這個並且遇到了一些錯誤。

我這才發現這個代碼是非常有益的出發點

public class Main 
{ 
    public static void main(String args[]) 
    { 
     try 
     { 
     Runtime rt = Runtime.getRuntime(); 
     String cmdString = "cmd /c dir"; 

     System.out.println(cmdString); 
     Process pr = rt.exec(cmdString); 

     BufferedReader input = new BufferedReader(new InputStreamReader(
                pr.getInputStream())); 

     String line = null; 

     while ((line = input.readLine()) != null) 
     { 
      System.out.println(line); 
     } 

     int exitVal = pr.waitFor(); 
     System.out.println("Exited with error code " + exitVal); 

     } 
     catch (Exception e) 
     { 
     System.out.println(e.toString()); 
     e.printStackTrace(); 
     } 
    } 
} 

它打印出的dir命令的結果。然而,當我修改它像這樣

public class Main 
{ 
    public static void main(String args[]) 
    { 
     try 
     { 
     Runtime rt = Runtime.getRuntime(); 
     String imageFilePath = "\"C:\\Program Files (x86)\\Tesseract-OCR\\doc\\eurotext.tif\""; 
     String outputFilePath = "\"C:\\Users\\Dreadnought\\Documents\\TestingFolder\\eurotext-example\""; 
     String[] commands = {"cmd", "/c", "tesseract", imageFilePath, outputFilePath }; 

     Process pr = rt.exec(commands); 

     BufferedReader input = new BufferedReader(new InputStreamReader(
       pr.getInputStream())); 

     String line = null; 

     while ((line = input.readLine()) != null) 
     { 
      System.out.println(line); 
     } 

     int exitVal = pr.waitFor(); 
     System.out.println("Exited with error code " + exitVal); 
     } 
     catch (Exception e) 
     { 
     System.out.println(e.toString()); 
     e.printStackTrace(); 
     } 
    } 
} 

它輸出的唯一東西是Exited with error code 1。如果過程以錯誤結束,則這是預期的輸出。

我甚至嘗試通過"cmd /c tesseract \"C:\\Program Files (x86)\\Tesseract-OCR\\doc\\eurotext.tif\" \"C:\\Users\\Dreadnought\\Documents\\TestingFolder\\eurotext-example\"",我最終有同樣的錯誤。

根據Using Quotes within getRuntime().exec我認爲問題在於我曾經試圖擺脫引號,所以這就是爲什麼我傳入一個字符串數組。但我仍然得到Exited with error code 1

是否可以使用java Runtime.getRuntime().exec()命令執行命令行程序?


編輯:問題還是存在的

我曾嘗試不使用「CMD/C」在同一直線上的推理思維的葉夫根尼·Dorofeev和Nandkumar Tekale以下建議。但是,我得到了一種不同的錯誤:

java.io.IOException: Cannot run program "tesseract": CreateProcess error=2, The system cannot find the file specified 
java.io.IOException: Cannot run program "tesseract": CreateProcess error=2, The system cannot find the file specified 
    at java.lang.ProcessBuilder.start(Unknown Source) 
    at java.lang.Runtime.exec(Unknown Source) 
    at java.lang.Runtime.exec(Unknown Source) 
    at Main.main(Main.java:15) 
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified 
    at java.lang.ProcessImpl.create(Native Method) 
    at java.lang.ProcessImpl.<init>(Unknown Source) 
    at java.lang.ProcessImpl.start(Unknown Source) 
... 4 more 

也許這會提供更多信息?我真的很好奇導致這個問題的原因。無論我是否將轉義引號添加到我的參數中,問題都是一樣的。


編輯2:一時心血來潮我提供了一個絕對路徑的Tesseract可執行文件,而不是使用cmd /c工作就像一個魅力。我想問題是Runtime.getRuntime().exec()不能調用環境變量嗎?

+0

我不知道,但問題可能會存在' C:\\ Program Files(x86)'在路徑中包含空格 –

+0

我認爲這是問題的根源,這就是爲什麼我試圖使用引號,但如果那些不是我rk與exec,你有什麼建議可以做這項工作嗎? – Samuel

+0

您正將一個數組傳遞給'rt.exec()'。不要在你的論點的開頭和結尾加上引號。這是關於如何將參數拆分的shell的信息,但是您已經完成了這些。 –

回答

1

well tesseract是外部命令,所以你不需要使用它與cmd。將tesseract添加到環境變量。使用直接命令如下:

String[] commands = {"tesseract", imageFilePath, outputFilePath }; 

存在狀態1表示錯誤的功能。請參見process exit status

+0

tesseract已經在環境變量中。 – Samuel

+0

你是否檢查直接在cmd提示符上運行它? –

+0

是的,它在命令提示符下工作得很好 – Samuel

0

另一個解決方法無需重新編譯和部署即可使用舊的DOS樣式路徑,例如C:\Program Files將爲C:\Progra~1。當然這隻有在你閱讀來自配置文件或數據庫和註冊表的路徑時纔會有幫助。

0

另一個解決方法是爲文件提供完整的安裝路徑,如/usr/local/Cellar/tesseract/3.02.02/斌/正方體」

0

你沒有捕捉STDERR,所以當出現錯誤時,你不會從STDOUT(你正在拍攝)接收這些嘗試:

BufferedReader input = new BufferedReader(new InputStreamReader(
       pr.getErrorStream()));