How to get java getRuntime().exec() to run a command-line program with arguments?
Asked Answered
S

4

19

I've been trying to write a java program that uses the Runtime.getRuntime().exec() method to use the command-line to run an instance of the program "tesseract".

Some background, Tesseract is a free open source program that is used to perform OCR (Optical Character Recognition) on pictures. It takes in a picture file and outputs a text document. It is a command-line program that uses this command to run

(from within the command prompt shell)

tesseract imageFilePath outFilePath [optional arguments] 

example:

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

the first argument calls the tesseract program, the second is the absolute path to the image file and the last argument is the path and name of what the output file should be. Tesseract only requires the name of the output file it does not require the extension.

Working from the command prompt this works perfect. However, I was wanting to run this from a java program and was running into some errors.

I found this this code to be very helpful as a starting off point

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();
      }
   }
}

It prints out the result of the dir command. However when I modified it like so

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();
      }
   }
}

The only thing it outputs is Exited with error code 1. This is the expected output if the Process ended with an error.

I have even tried passing "cmd /c tesseract \"C:\\Program Files (x86)\\Tesseract-OCR\\doc\\eurotext.tif\" \"C:\\Users\\Dreadnought\\Documents\\TestingFolder\\eurotext-example\"" and I ended up having the same error.

According to Using Quotes within getRuntime().exec I thought problem was that I was that i had tried to escape the quotes, so that is why I passed in a String array. But I am still getting the Exited with error code 1.

Is it possible to execute a command-line program with the java Runtime.getRuntime().exec() command?


EDIT: The problem is still occuring

I have tried not using "cmd /c" thinking along the same line of reasoning as Evgeniy Dorofeev and Nandkumar Tekale suggested below. However, I get a different sort of error:

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

Maybe this gives more information? I am really curious about what is causing this problem. Also the problem is the same whether or not I add the escaped quotations to my arguments.


EDIT 2: On a whim I provided an absolute path to the tesseract executable and not using the cmd /c worked like a charm. I guess the question is can Runtime.getRuntime().exec() not call environment variables?

Saire answered 20/11, 2012 at 5:49 Comment(6)
I am not sure but problem might exist with C:\\Program Files (x86) which contain space in path.Lilia
I figured this was the root of the problem which is why I tried to use the quotes, but if those don't work with exec, do you have a suggestion on how I might make this work?Saire
You're passing an array to rt.exec(). Don't put quotes at the beginning and end of your arguments. It is an information for the shell on how to split the arguments apart, but you've already done that.Comminute
If I don't use quotes then how can I get the C:\\Program Files (x86) to stay together? However, I have tried it without the quotes and still doesn't work.Saire
yes I used it without the cmd /cSaire
@Saire Consider marking this question as answered, and ask your follow-up question about Runtime.exec and environment variables separately.Dianemarie
A
5

You are not capturing STDERR, so when errors occur you do not receive them from STDOUT (which you are capturing). Try:

BufferedReader input = new BufferedReader(new InputStreamReader(
               pr.getErrorStream()));
Alps answered 7/10, 2016 at 21:53 Comment(0)
L
3

well tesseract is external command so you do not need to use it with cmd. Add tesseract to environment variables. Use direct command as :

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

Exist status 1 means Incorrect function. See process exit status

Lilia answered 20/11, 2012 at 5:53 Comment(1)
did you check running it directly on cmd prompt?Lilia
L
1

Another workaround without having to recompile and deploy is using the old DOS style paths for e.g C:\Program Files would be C:\Progra~1. Of course this will be helpful only if you are reading the paths from a config file or DB and registry etc.

Leprous answered 2/5, 2013 at 15:23 Comment(0)
C
1

another workaround is give complete installation path of file like /usr/local/Cellar/tesseract/3.02.02/bin/tesseract"

Constitutional answered 14/6, 2013 at 21:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.