Как получить Java getRuntime(). Exec() для запуска программы командной строки с аргументами?
Я пытался написать программу Java, которая использует Runtime.getRuntime().exec()
метод использования командной строки для запуска экземпляра программы "tesseract".
В некотором смысле, 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\""
и я в конечном итоге с той же ошибкой.
В соответствии с использованием кавычек в getRuntime(). Exec я думал, что проблема в том, что я пытался избежать кавычек, поэтому я передал массив String. Но я все еще получаю Exited with error code 1
,
Можно ли выполнить программу командной строки с Java Runtime.getRuntime().exec()
команда?
РЕДАКТИРОВАТЬ: проблема все еще происходит
Я пытался не использовать "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.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
... 4 more
Может быть, это дает больше информации? Мне действительно любопытно, что вызывает эту проблему. Кроме того, проблема в том, добавляю ли я экранированные цитаты к своим аргументам.
РЕДАКТИРОВАТЬ 2: По какой-то причине я указал абсолютный путь к исполняемому файлу tesseract и не использовал cmd /c
работал как шарм. Я думаю, что вопрос может Runtime.getRuntime().exec()
не вызывать переменные среды?
5 ответов
Вы не захватываете STDERR, поэтому при возникновении ошибок вы не получаете их от STDOUT (который вы захватываете). Пытаться:
BufferedReader input = new BufferedReader(new InputStreamReader(
pr.getErrorStream()));
Что ж tesseract
является внешней командой, поэтому вам не нужно использовать ее с cmd
, добавлять tesseract
к переменным среды. Используйте прямую команду как:
String[] commands = {"tesseract", imageFilePath, outputFilePath };
Существующий статус 1 означает неправильную функцию. Посмотреть статус выхода процесса
Другой обходной путь без перекомпиляции и развертывания - использование старых путей в стиле DOS, например, для C:\Program Files
было бы C:\Progra~1
, Конечно, это будет полезно, только если вы читаете пути из конфигурационного файла или БД, реестра и т. Д.
Другой обходной путь - указать полный путь установки файла, например /usr/local/Cellar/tesseract/3.02.02/bin/tesseract"
Вы можете попробовать мойjaxec
библиотека:
import com.yegor256.Jaxec;
new Jaxec("cmd", "/c", "dir").exec();
Он будет использоватьRuntime
«под капотом», но также зарегистрирует его вывод, проверит значение кода выхода и дождется завершения процесса.