如何让java getRuntime()。exec()运行带参数的命令行程序?

我一直在尝试编写一个使用Runtime.getRuntime().exec()方法的java程序来使用命令行来运行程序“tesseract”的实例。

一些背景,Tesseract是一个免费的开源程序,用于在图片上执行OCR(光学字符识别)。 它接收图片文件并输出文本文档。 它是一个使用此命令运行的命令行程序

(从命令提示符shell中)

 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\""我最终遇到了同样的错误。

根据getRuntime()。exec中的Using Quotes我认为问题是我曾试图逃避引号,所以这就是我传入String数组的原因。 但我仍然得到Exited with error code 1

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


编辑 :问题仍然存在

我试过不按照与Evgeniy Dorofeev和Nandkumar Tekale在下面提出的推理相同的方式使用“cmd / c”思考。 但是,我得到了一种不同的错误:

 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.(Unknown Source) at java.lang.ProcessImpl.start(Unknown Source) ... 4 more 

也许这会提供更多信息? 我真的很好奇是什么导致了这个问题。 无论我是否将转义引用添加到我的参数中,问题都是一样的。


编辑2 :一时兴起,我提供了tesseract可执行文件的绝对路径,而不是使用像魅力一样的cmd /c 。 我想问题是Runtime.getRuntime().exec()不能调用环境变量吗?

well tesseract是外部命令,因此您不需要将其与cmd一起使用。 将tesseract添加到环境变量中。 使用直接命令:

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

存在状态1表示function不正确。 查看流程退出状态

无需重新编译和部署的另一种解决方法是使用旧的DOS样式路径,例如C:\Program Files将是C:\Progra~1 。 当然,只有在从配置文件或数据库和注册表等中读取路径时,这才有用。

另一种解决方法是提供文件的完整安装路径,如/usr/local/Cellar/tesseract/3.02.02/bin/tesseract“

您没有捕获STDERR,因此当发生错误时,您不会从STDOUT(您正在捕获它)中收到它们。 尝试:

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