2012-09-21 27 views
9

¿Hay una manera fácil de leer la salida del subproceso sin búfer? Intento llamar a un programa C desde Java, pero aparentemente está bloqueado en bloque cuando está conectado a la tubería y al buffer de línea solo cuando está conectado a la consola. No puedo modificar el programa C.stdout de subproceso sin búfer en Windows

Quizás haya una manera de engañar al programa haciéndole creer que está conectado a la consola. Puntos de bonificación para una solución que también funciona en Linux.

+1

Puede abrir un ssh en la misma máquina y ejecutarlo de esa manera. Sospecho que no hay nada simple para hacer esto. –

+0

"buffer de línea" se produce en el nivel del sistema operativo. En Linux, por ejemplo, haría un "ioctl()" para configurar su terminal en "modo sin formato". ¿Quizás pueda buscar "E/S de terminal de Java", "maldiciones de Java" o palabras clave similares? – paulsm4

+0

Ya hice una búsqueda exhaustiva en Internet y en SO. Esto parece ser un problema común, pero no he encontrado una sola solución para Windows –

Respuesta

-1

OK -

1) "búfer de línea de entrada" es un lenguaje común para programas en modo consola, que data del Unix original y terminales VTxx en modo serie.

2) Puede leer E/S "en bruto, sin búfer" (una pulsación de tecla a la vez, en lugar de una línea a la vez), pero los detalles son específicos del sistema operativo. Sea lo que sea que necesite para hacer en un sistema operativo específico, casi con seguridad puede hacer desde Java.

3) Parece que quiere ser capaz de interceptar una tecla "flecha hacia arriba" o tecla "avanzar página", como ocurre, en un teclado de Windows. Quizás para jugar un juego o para interactuar con una interfaz de usuario en modo consola.

4) Hay varias opciones. Uno es posible que desee considerar es la API "robot", que se utiliza para la prueba:

Si eso no es suficiente, por favor, dar más detalles sobre exactamente cómo se está tratando de obtener su Java programa para interactuar con el programa C (y aclarar si la plataforma es de hecho Windows y un prompt de DOS).

+0

No necesito entrada sin procesar, bastará con el buffer de línea. Intenté 'Runtime.getRuntime() .exec (comando);' o 'nuevo ProcessBuilder (comando) .start();' para ejecutar el programa C, y luego 'process.getInputStream()' pero me dio un bloqueo- corriente amortiguada. –

-1

Usted puede redirigir la salida a un archivo C y luego la cola el archivo desde otro hilo en Java utilizando

org.apache.commons.io.input.Tailer 
+0

Desafortunadamente, la escritura en un archivo casi seguro también se almacenará en el búfer. –

+0

El usuario en el siguiente comentario dice que el almacenamiento en línea está bien. Queremos redirigir la salida directamente desde el ejecutable y no desde Java, quizás eso funcione. – user1569047

+0

Nunca escuché nada en Windows haciendo un buffer de línea; por lo general, la salida se almacena en búfer o sin búfer. En cualquier caso, si la redirección a un conducto está bloqueada en búfer, la redirección a un archivo casi seguro también será bloqueada. Este no es un problema de Java, tiene que ver con el comportamiento de la biblioteca C runtime en el subproceso. –

0

¿Ha intentado utilizar ambiente BUF_1_ variable = 0?

+0

Por lo que puedo decir de una búsqueda en Google, este fue en un momento un mecanismo propuesto para suprimir el almacenamiento en búfer en la biblioteca glibc, pero los desarrolladores lo rechazaron. ¿Tiene una mejor referencia? (Lo he intentado con Visual Studio y parece que no funciona.) –

-1

La mejor manera de hacerlo es usando hilos para leer la salida

Lo que me gustaría hacer es: el uso de un rescatable (un Ejecutable también funcionará) donde doy la entrada del proceso (process.getInputStream ()) y la salida donde quiero almacenar la salida. Lo mismo debe hacerse para el StdErr. El resultado resultante se puede leer usando lo que quieras.

public Object call() throws IOException { 
     int bytesRead; 
     byte[] b = new byte [ this.maxBlockSize ]; 

     try { 
      while ((bytesRead = this.input.read (b)) != -1) { 
       this.output.write (b, 0, bytesRead); 
      } 
     } finally { 
      if (this.output != null) { 
       this.output.close(); 
      } 
     } 
     return null; 
    } 
+0

Eso no soluciona el problema de los PO. La salida se almacena temporalmente en el proceso secundario, no en el proceso principal. –

+0

Si se hace de esta manera, no importa si está bloqueando porque se lee en una secuencia separada. – azl

+2

Se está perdiendo el punto, que es que necesita la salida del proceso hijo de inmediato, no en algún momento futuro indeterminado cuando finalmente se llena el búfer stdout del niño. Hacer que la lectura no bloquee significa que su programa quizás pueda hacer otro trabajo mientras espera el proceso secundario, pero no ayuda a obtener el resultado más rápido. (En particular, considere el caso donde el proceso hijo está esperando la entrada, pero el proceso padre necesita ver el resultado antes de saber qué entrada enviar, los procesos se estancarán). –

1

No es una gran solución, pero la biblioteca de tiempo de ejecución probablemente no almacena los puertos serie por lo que si estás desesperado suficiente se puede utilizar un emulador de módem nulo como com0com o un derivado del mismo.

Cuestiones relacionadas