web-dev-qa-db-fra.com

Comment obtenir Java getRuntime (). Exec () pour exécuter un programme en ligne de commande avec des arguments?

J'ai essayé d'écrire un programme Java qui utilise la méthode Runtime.getRuntime().exec() pour utiliser la ligne de commande afin d'exécuter une instance du programme "tesseract".

Un peu d’arrière-plan, Tesseract est un programme gratuit et à source ouverte utilisé pour effectuer la reconnaissance optique de caractères (OCR) sur les images. Il prend dans un fichier image et génère un document texte. C'est un programme en ligne de commande qui utilise cette commande pour exécuter

(depuis la commande Invite Shell)

tesseract imageFilePath outFilePath [optional arguments] 

exemple:

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

le premier argument appelle le programme tesseract, le second est le chemin absolu du fichier image et le dernier argument est le chemin et le nom du fichier de sortie. Tesseract n’exige que le nom du fichier de sortie sans extension.

Depuis l'invite de commande, cela fonctionne parfaitement. Cependant, je voulais exécuter ceci à partir d'un programme Java et courais quelques erreurs.

J'ai trouvé ce code très utile comme point de départ

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

Il affiche le résultat de la commande dir. Cependant, quand je l'ai modifié comme si

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

La seule chose qu'il génère est Exited with error code 1. C'est la sortie attendue si le processus s'est terminé avec une erreur.

J'ai même essayé de passer "cmd /c tesseract \"C:\\Program Files (x86)\\Tesseract-OCR\\doc\\eurotext.tif\" \"C:\\Users\\Dreadnought\\Documents\\TestingFolder\\eurotext-example\"" et j'ai fini par avoir la même erreur.

Selon Utilisation de Quotes dans getRuntime (). Exec Je pensais que le problème était que j’avais essayé d’échapper aux guillemets, c’est pourquoi j’ai passé dans un tableau String. Mais je reçois toujours le Exited with error code 1.

Est-il possible d'exécuter un programme en ligne de commande avec la commande Java Runtime.getRuntime().exec()?


EDIT: le problème persiste

J'ai essayé de ne pas utiliser "cmd/c" en suivant le même raisonnement que Evgeniy Dorofeev et Nandkumar Tekale suggéré ci-dessous. Cependant, j'obtiens un type d'erreur différent:

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

Peut-être que cela donne plus d'informations? Je suis vraiment curieux de savoir ce qui cause ce problème. De plus, le problème est le même, que j'ajoute ou non les citations échappées à mes arguments.


EDIT 2 : Sur un coup de tête, j’ai fourni un chemin absolu vers l’exécutable tesseract et je n’ai pas utilisé le cmd /c fonctionnait à merveille. Je suppose que la question est la suivante: Runtime.getRuntime().exec() peut-il ne pas appeler de variables d’environnement?

9
Samuel

bien tesseract est une commande externe, vous n’avez donc pas besoin de l’utiliser avec cmd. Ajoutez tesseract aux variables d'environnement. Utilisez la commande directe comme:

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

Statut existant 1 signifie fonction incorrecte. Voir Traiter le statut de sortie

1
Nandkumar Tekale

Vous ne capturez pas STDERR. Par conséquent, lorsque des erreurs se produisent, vous ne les recevez pas de STDOUT (que vous capturez). Essayer:

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

Une autre solution de contournement sans avoir à recompiler et à déployer l’utilisation des anciens chemins de style DOS, par exemple C:\Program Files, serait C:\Progra~1. Bien sûr, cela ne sera utile que si vous lisez les chemins d’un fichier de configuration, d’une base de données et d’un registre, etc.

0
user1382115

une autre solution consiste à donner le chemin d’installation complet du fichier tel que /usr/local/Cellar/tesseract/3.02.02/bin/tesseract "

0
Raj Pandiri