Pergunta

Se eu iniciar um processo via Java Construtor de Processos classe, tenho acesso total aos fluxos de entrada, saída padrão e erro padrão desse processo como Java InputStreams e OutputStreams.No entanto, não consigo encontrar uma maneira de conectar perfeitamente esses fluxos a System.in, System.out, e System.err.

É possível usar redirectErrorStream() para obter um único InputStream que contém a saída padrão e o erro padrão do subprocesso, e apenas percorrer isso e enviá-lo através da minha saída padrão - mas não consigo encontrar uma maneira de fazer isso e deixar o usuário digitar no processo, como ele ou ela poderia se eu usei o C system() chamar.

Isso parece ser possível no Java SE 7 quando for lançado - só estou me perguntando se há uma solução alternativa agora.Pontos de bônus se o resultado de isatty() no processo filho realiza o redirecionamento.

Foi útil?

Solução

Você precisará copiar o Processo fluxos out, err e input para as versões do sistema.A maneira mais fácil de fazer isso é usar o IOUtils classe do pacote Commons IO.O método de cópia parece ser o que você precisa.As invocações do método copy precisarão estar em threads separadas.

Aqui está o código básico:

// Assume you already have a processBuilder all configured and ready to go
final Process process = processBuilder.start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(process.getOutputStream(), System.out);
} } ).start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(process.getErrorStream(), System.err);
} } ).start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(System.in, process.getInputStream());
} } ).start();

Outras dicas

Uma variação da resposta de John que compila e não exige que você use o Commons IO:

private static void pipeOutput(Process process) {
    pipe(process.getErrorStream(), System.err);
    pipe(process.getInputStream(), System.out);
}

private static void pipe(final InputStream src, final PrintStream dest) {
    new Thread(new Runnable() {
        public void run() {
            try {
                byte[] buffer = new byte[1024];
                for (int n = 0; n != -1; n = src.read(buffer)) {
                    dest.write(buffer, 0, n);
                }
            } catch (IOException e) { // just exit
            }
        }
    }).start();
}

Para System.in use o seguinte pipein() em vez de pipe()

pipein(System.in, p.getOutputStream());

Implementação:

private static void pipein(final InputStream src, final OutputStream dest) {

    new Thread(new Runnable() {
        public void run() {
            try {
               int ret = -1;
               while ((ret = System.in.read()) != -1) {
                  dest.write(ret);
                  dest.flush();
               }
            } catch (IOException e) { // just exit
            }
        }
    }).start();

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top