2010-05-20 21 views
7

Estoy intentando ejecutar un programa desde el código de Java. Aquí está mi código:Ejecutar programa externo desde Java

public static void main(String argv[]) { 
    try { 
     String line; 
     Process p = Runtime.getRuntime().exec(
      "/bin/bash -c ls > OutputFileNames.txt"); 
     BufferedReader input = new BufferedReader(
      new InputStreamReader(p.getInputStream())); 
     while ((line = input.readLine()) != null) { 
     System.out.println(line); 
     } 
     input.close(); 
    } catch (Exception err) { 
     err.printStackTrace(); 
    } 
} 

Mi sistema operativo es Mac OS X 10.6.

Si elimino el "> OutputFileNames.txt" del método getRuntime().exec(), todos los nombres de los archivos están bien impresos en la consola. Pero necesito que se imprima en un archivo.

Además, si cambio de la orden de:

Process p = Runtime.getRuntime().exec(
    "cmd \c dir > OutputFileNames.txt"); 

y ejecutarlo en Windows, se ejecuta e imprime los resultados en el archivo perfectamente bien también.

He leído las otras publicaciones para ejecutar otra aplicación desde Java, pero ninguna parecía estar relacionada con mi problema.

Realmente agradecería cualquier ayuda que pueda obtener.

Gracias,

+0

Si lo único que desea hacer es listar los archivos en un directorio, entonces no hay razón para hacerlo por un programa externo; puede simplemente usar 'File.listFiles()' y escribir el resultado en un archivo usted mismo. Eso funcionará en cualquier sistema operativo y no necesita un código específico para Mac OS X o Windows. – Jesper

+0

Eso es algo básico que estoy intentando. Finalmente, lo que quiero hacer es ejecutar un programa externo llamado e imprimir la salida de ese programa en un archivo, luego analizar el archivo desde Java para hacer otras cosas útiles. –

+1

¿Ha intentado usar .exec (new String [] {"/ bin/bash", "-c", "ls> OutputFileNames.txt"}); ¿También falla? – Anton

Respuesta

8

Para conseguir la redirección funcione como está escrito, lo que necesita hacer esto:

Process p = Runtime.getRuntime().exec(
     new String[]{"/bin/bash", "-c", "ls > OutputFileNames.txt"}); 

El problema que se estaba ejecutando en es la forma simplista que esa Runtime.exec(String) divide un comando alinear en argumentos.

Si se va a ejecutar ese comando (como es) en el intérprete de comandos, que habría tenido que han entrado como:

$ /bin/bash -c "ls > OutputFileNames.txt" 

porque la opción "c" de "golpe" requiere la línea de comando para la shell generada como un único argumento de shell. Pero si tuviera que poner las comillas desnudas en Java String, el método Runtime.exec(String) aún se equivoca al dividir. La única solución es proporcionar los argumentos del comando como una matriz.

+0

el javadoc indica que la línea de comando está dividida: "El argumento del comando se analiza en tokens y luego se ejecuta como un comando en un proceso separado. El análisis del token se hace mediante un StringTokenizer ...". Consulte http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#exec%28java.lang.String%29 nuevo StringTokenizer (comando) – mdma

+0

@mdma - y eso por supuesto es el problema. StringTokenizer no entiende las cadenas entre comillas. –

+0

Ok, veo su edición, que ha citado el comando para golpear. No noté que la línea de comando original era incorrecta. – mdma

1

Un par de cosas para mirar.

  • cheque que su directorio de programa se ejecuta en (mediante la ejecución de pwd la misma manera), a continuación, comprobar para asegurarse de que tiene permisos para escribir en ese directorio.
  • vea si ese archivo OutputFileNames.txt ya existe (y compruebe los permisos).
  • si el archivo existe, elimínelo y vuelva a ejecutarlo para ver si se vuelve a crear, y mire el contenido si lo hace.
  • intente utilizar el comando "/bin/bash -c 'ls > OutputFileNames.txt'" - puede ser que la salida es bash no la misma que la salida ls (en su ejemplo la redirección podría estar aplicando a bash en lugar de ls).
1

El problema está sucediendo porque la salida estándar del proceso se está dirigiendo al archivo, por lo que la java Process no puede recoger la salida.

Si desea que la salida escribe en un archivo, y estará disponible para su lectura en java, entonces usted tiene dos opciones:

  1. Mantenga la redirección en su lugar, y luego lee el anuncio de la OutputFile.txt en Java, por ejemplo usando new FileReader("OutputFile.txt"). Tenga en cuenta que exec() es asincrónico y puede regresar antes de que el proceso haya terminado de escribir en el archivo, por lo que deberá esperar a que el Proceso salga, usando Process.waitFor().
  2. Elimina la redirección y lee el listado directamente en Java (como lo estás haciendo). Luego puedes escribir esta lista en un archivo usando FileWriter.

La conclusión es que no puede usar tanto la redirección como la salida del Proceso al mismo tiempo, es una u otra.

EDITAR: Sus comentarios indican que 1) es el enfoque preferido. Esto escribirá el resultado en un archivo (usando el shell del sistema operativo) que luego leerá desde java cuando el proceso finalice.

Cuestiones relacionadas