Pregunta

im tratando de llegar a un diseño para un contenedor para su uso cuando invocar las utilidades de línea de comandos en Java. El problema con runtime.exec () es que se necesita para mantener la lectura del proceso y errar corrientes o se cuelga cuando se llena sus buffers. esto me ha llevado a la siguiente diseño:

public class CommandLineInterface {
    private final Thread stdOutThread;
    private final Thread stdErrThread;
    private final OutputStreamWriter stdin;
    private final History history;


    public CommandLineInterface(String command) throws IOException {
        this.history = new History();
        this.history.addEntry(new HistoryEntry(EntryTypeEnum.INPUT, command));
        Process process = Runtime.getRuntime().exec(command);
        stdin = new OutputStreamWriter(process.getOutputStream());
        stdOutThread = new Thread(new Leech(process.getInputStream(), history, EntryTypeEnum.OUTPUT));
        stdOutThread.setDaemon(true);
        stdOutThread.start();
        stdErrThread = new Thread(new Leech(process.getErrorStream(), history, EntryTypeEnum.ERROR));
        stdErrThread.setDaemon(true);
        stdErrThread.start();
    }

    public void write(String input) throws IOException {
        this.history.addEntry(new HistoryEntry(EntryTypeEnum.INPUT, input));
        stdin.write(input);
        stdin.write("\n");
        stdin.flush();
    }
}

y

public class Leech implements Runnable{
    private final InputStream stream;
    private final History history;
    private final EntryTypeEnum type;
    private volatile boolean alive = true;


    public Leech(InputStream stream, History history, EntryTypeEnum type) {
        this.stream = stream;
        this.history = history;
        this.type = type;
    }

    public void run() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        String line;
        try {
            while(alive) {
                line = reader.readLine();
                if (line==null) break;
                history.addEntry(new HistoryEntry(type, line));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

mi problema es con la clase Leech (utilizado para "sanguijuela" proceso y errar corrientes y darles de comer en la historia - que actúa como un archivo de registro) - por un lado, la lectura de líneas completas es agradable y fácil (y lo que estoy haciendo actualmente), pero significa que falto a la última línea (normalmente la línea de mensajes). Sólo veo la línea de mensajes al ejecutar el siguiente comando (porque no hay ningún salto de línea hasta ese momento). Por otro lado, si leo caracteres mí mismo, ¿cómo puedo saber cuando el proceso está "hecho"? (Ya sea completa o en espera de entrada) ¿alguien ha intentado algo parecido a la espera 100 milisegundos desde el último resultado del proceso y declarando que "hecho"?

cualquier mejores ideas sobre cómo puedo aplicar un bonito envoltorio sobre cosas como runtime.exec ( "cmd.exe")?

¿Fue útil?

Solución

PlexusUtils que es utilizado por Apache Maven 2 para ejecutar todos los procesos externos.

Otros consejos

Yo estaba buscando lo mismo que a mí mismo, y me encontré con un puerto de Java de esperar, llamado ExpectJ . No he probado todavía, pero parece prometedor

Me gustaría leer la entrada con la corriente y luego escribirlo en un ByteArrayOutputStream. La matriz de bytes seguirá creciendo hasta que ya no hay bytes disponibles para leer. En este punto se le vaciar los datos a la historia mediante la conversión de la matriz de bytes en una cadena y partiéndolo en el line.separator plataforma. A continuación, puede iterar sobre las líneas para agregar las entradas del historial. El ByteArrayOutputStream luego se reinicia y los bloques de bucle tiempo hasta que hay más datos o se alcanza el final de la corriente (probablemente porque el proceso se realiza).

public void run() {
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    int bite;
    try {
        while((bite = stream.read()) != -1) {
            out.write(bite);

            if (stream.available() == 0) {
                String string = new String(out.toByteArray());
                for (String line : string.split(
                        System.getProperty("line.separator"))) {
                    history.addEntry(new HistoryEntry(type, line));
                }

                out.reset();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Esto se asegurará de recoger la última línea de la entrada y se resuelve el problema de saber cuando se termina la corriente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top