Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace https://old.chuidiang.org

Arrancar un programa externo desde Java

Aunque es un práctica no muy aconsejable, puesto que se pierde el objetivo básico de java, que es poder ejecutar el programa en cualquier plataforma, a veces es necesario llamar a ejecutables externos. Por ejemplo, podemos querer desde java lanzar el navegador, el acrobat reader para ver un PDF, etc.

Vamos a ver aquí cómo hacerlo. Y de paso, un pequeño problema con algunos comandos de Windows que tienen una peculiaridad especial.

Para arrancar un ejecutable externo desde java tenemos la clase Runtime.

El modo de arrancar esta ejecutable externo es el siguiente:
 

try
{
   /* directorio/ejecutable es el path del ejecutable y un nombre */
   Process p = Runtime.getRuntime().exec ("directorio/ejecutable");
}
catch (Exception e)
{
   /* Se lanza una excepción si no se encuentra en ejecutable o el fichero no es ejecutable. */
}

Hay una excepción que debemos capturar. Se produce en caso de que no se encuentre el ejecutable que indicamos o si se encuentra, que no se pueda arrancar (no tengamos permisos de acceso, el fichero no sea un ejecutable, etc, etc).

Si no ponemos el path del ejecutable, el directorio en el que se encuentra debe estar en la variable de entorno PATH, si no, no sabrá dónde econtrar el ejecutable.

Un detalle para windows

Para poder aplicar esto, es necesario que el ejecutable sea un fichero que exista. En windows, heredados del antiguo ms-dos, existen ciertos comandos que no poseen un ejecutable propio. Por ejemplo, el comando dir, por más que busquemos, no encontraremos un dir.com ni un dir.exe ni un dir.bat ni nada parecido. En el antiguo ms-dos había comandos internos y externos. Los primeros los "entendía" el sistema operativo, no hacía falta un ejecutable. Escribiamos "dir" y el ms-dos, sin necesidad de buscar el ejecutable asociado, sabía lo que tenía que hacer. Los externos son los que tenían ejecutable asociado.

Estos comandos que no tienen ejecutable, no se puede arrancar directamente desde java. Hay que hacerlo de forma "indirecta". Hay que arrancar una ventana de ms-dos y decirle cual es el comando que tiene que ejecutar.

Cuando desde windows abrimos una ventana de ms-dos, estamos ejecutando un programa que antes se llamaba command.com. Ahora, además de este, hay un cmd.exe. Este programa es el que ejecuta el comando dir. Realmente dir no es un ejecutable, es una palabra/parámetro que cmd.exe entiende y hace algo en consecuencia, mostrar los ficheros del directorio actual.

Por ello, si queremos arrancar un dir desde java, debemos arrancar un cmd dándole como opción que ejecute un dir. Es decir

Process p = Runtime.getRuntime().exec ("cmd /c dir");

Esto no pasa en linux (no hay comandos internos, todos los comandos tienen ejecutable asociado). Con windows tendremos que mirar si hay o no ejecuable externo. Por ejemplo, estos sí tienen ejecutable aparte: notepad, netstat, format, etc.

Leer la salida del programa

Cuando se ejecuta un programa desde java, su salida por pantalla ya no sale. ¿Qué está pasando?. Al ejecutar un programa desde java, la salida del programa se redirige a nuestro programa java, en vez de a al pantalla. Esto es útil porque así, desde el programa java, podemos leer lo que está sacando el ejecutable externo y hacer algo con ello.

Para leer lo que saca el ejecutable externo, debemos usar el Process que nos devuelve Runtime.exec(). Este Process representa de alguna forma al ejecutable externos mientras está corriendo. Con él podemos obtener la salida del programa, su salida de error e incluso enviarle datos como si se estuvieran tecleando. También podriamos hacer que el programa termine o esperar a que lo haga él solo.

Si queremos leer su salida, obtenemos un InputStream por medio del método getInputStream() y leemos en él. Puesto que un InputStream es algo incómodo para leer cadenas de texto, lo metemos dentro de algo un poco más cómodo. El código para todo ello es este:
 

/* Se obtiene el stream de salida del programa */
InputStream is = p.getInputStream();
            
/* Se prepara un BufferedReader para poder leer la salida más comodamente. */
BufferedReader br = new BufferedReader (new InputStreamReader (is));

Ahora leer es simple. El BufferedReader tiene un método readLine() que nos devuelve directamente una línea de texto en forma de String.

Un ejemplo

En PruebaRuntime.java tienes un código que ejecuta un dir de windows y saca su salida por pantalla. Para eso simplemente hacemos dir desde una ventana de ms-dos, pero dejo a tu imaginación inventar algo más útil que esto. Si te lo bajas, quítale la extensión .txt y mételo en un directorio <un_path_cualquiera>/chuidiang/ejemplos/runtime/PruebaRuntime.java

/*
 * PruebaRuntime.java
 *
 * Created on 17 de abril de 2005, 15:43
 */


package chuidiang.ejemplos.runtime;

import java.io.*;

/**
 * Ejemplo simple de arranque de un programa externo desde java.
 * @author  Chuidiang
 */

public class PruebaRuntime {
    
    /** Creates a new instance of PruebaRuntime */
    public PruebaRuntime() 
    {
        try
        {
            // Se lanza el ejecutable.
            Process p=Runtime.getRuntime().exec ("cmd /c dir");
            
            // Se obtiene el stream de salida del programa
            InputStream is = p.getInputStream();
            
            /* Se prepara un bufferedReader para poder leer la salida más comodamente. */
            BufferedReader br = new BufferedReader (new InputStreamReader (is));
            
            // Se lee la primera linea
            String aux = br.readLine();
            
            // Mientras se haya leido alguna linea
            while (aux!=null)
            {
                // Se escribe la linea en pantalla
                System.out.println (aux);
                
                // y se lee la siguiente.
                aux = br.readLine();
            }
        } 
        catch (Exception e)
        {
            // Excepciones si hay algún problema al arrancar el ejecutable o al leer su salida.*/
            e.printStackTrace();
        }
    }
    
    /**
     * Crea la clase principal que ejecuta el comando dir y escribe en pantalla
     * lo que devuelve dicho comando.
     *
     * @param args the command line arguments
     */

    public static void main(String[] args) {
        new PruebaRuntime();
    }
}

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007:

Aviso Legal