2013-04-04 9 views
5

UPDATE: I found a crucial part to why this probably isn't working! I used System.setOut(out); where out is a special PrintStream to a JTextAreaStampa di un InputStream Java da un processo

Questo è il codice, ma il problema che sto avendo è che l'informazione viene stampato solo una volta finisco il processo.

public Constructor() { 
    main(); 
} 

private void main() { 
    btnStart.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      try { 
       ProcessBuilder builder = new ProcessBuilder("java", textFieldMemory.getText(), "-jar", myJar); 
       Process process = builder.start(); 
       InputStream inputStream = process.getInputStream(); 
       BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream), 1); 
       String line; 
       while ((line = bufferedReader.readLine()) != null) { 
        System.out.println(line); 
       } 
       inputStream.close(); 
       bufferedReader.close(); 
      } catch (IOException ioe) { 
       ioe.printStackTrace(); 
      } 
     } 
    }); 
} 

uscita corrente:

Line 1 
Line 2 
Line 3 
Line 4 
Line 5 

Questa è l'uscita corretta, ma viene soltanto stampata come un grande blocco quando termina il processo.

Qualcuno sa qual è il problema? Se è così puoi aiutarmi a spiegarmi perché questo sta accadendo, grazie in anticipo.

+2

L'uscita è stata tamponata nel 'BufferedReader', provare solo leggendo il contenuto dalla' InputStream' direttamente per vedere se fa una differenza – MadProgrammer

+1

Sono d'accordo con @MadProgrammer che il problema è probabilmente con il buffer. Tuttavia, suggerisco di impostare la dimensione del buffer 'BufferedReader' su 1 con [il suo costruttore di due parametri] (http://docs.oracle.com/javase/6/docs/api/java/io/BufferedReader.html# BufferedReader% 28java.io.Reader,% 20int% 29): 'new BufferedReader (new InputStreamReader (inputStream), 1)' – DaoWen

+0

L'utilizzo di ByteArrayOutputStream funzionerebbe meglio? Sono completamente nuovo agli stream, e questo mi disturba XD – Ciphor

risposta

8

L'elaborazione del flusso di output del processo in una thread separata potrebbe essere d'aiuto. Anche voi volete attendere in modo esplicito per il processo per terminare prima di continuare con la logica:

ProcessBuilder builder = new ProcessBuilder("java", 
     textFieldMemory.getText(), "-jar", myJar); 
final Process process = builder.start(); 
final Thread ioThread = new Thread() { 
    @Override 
    public void run() { 
     try { 
      final BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream())); 
      String line = null; 
      while ((line = reader.readLine()) != null) { 
       System.out.println(line); 
      } 
      reader.close(); 
     } catch (final Exception e) { 
      e.printStackTrace(); 
     } 
    } 
}; 
ioThread.start(); 

process.waitFor(); 
+0

Non ha funzionato per me, come ho detto, penso che abbia a che fare con questo ho reindirizzato l'output della console a un JTextArea. – Ciphor

+0

Sì, questo è un dettaglio abbastanza importante. È più che probabile che devi svuotare esplicitamente lo stream su ogni scrittura, quindi attivare un repaint di JTextArea, in modo che l'output venga visualizzato in tempo reale. – Perception

+0

Ho trovato qualcosa di interessante se si guarda il mio codice originale nella domanda e spostato 'inputStream.close();' nel ciclo while, ho ottenuto con successo la prima riga stampata nel mio 'JTextArea' e quindi lo stream è ovviamente chiuso. – Ciphor

4

In sostanza, da quel poco che le informazioni non v'è, suona come la vostra esecuzione del processo e la lettura del InputStream dall'interno thread evento Dispacciamento .

Qualsiasi cosa per bloccare l'EDT impedirà l'elaborazione di richieste di riverniciatura, invece, è necessario utilizzare qualcosa come un SwingWorker che ha funzionalità per consentire di aggiornare l'interfaccia utente con l'EDT.

Date un'occhiata a Concurrency in Swing per maggiori dettagli

enter image description here

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingWorker; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class PBDemo { 

    public static void main(String[] args) throws Exception { 
     new PBDemo(); 
    } 

    public PBDemo() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new BorderLayout()); 
      JTextArea ta = new JTextArea(); 
      add(new JScrollPane(ta)); 

      new ProcessWorker(ta).execute(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 
    } 

    public interface Consumer { 
     public void consume(String value);    
    } 

    public class ProcessWorker extends SwingWorker<Integer, String> implements Consumer { 

     private JTextArea textArea; 

     public ProcessWorker(JTextArea textArea) { 
      this.textArea = textArea; 
     } 

     @Override 
     protected void process(List<String> chunks) { 
      for (String value : chunks) { 
       textArea.append(value); 
      } 
     } 

     @Override 
     protected Integer doInBackground() throws Exception { 
      // Forced delay to allow the screen to update 
      Thread.sleep(5000); 
      publish("Starting...\n"); 
      int exitCode = 0; 
      ProcessBuilder pb = new ProcessBuilder("java.exe", "-jar", "HelloWorld.jar"); 
      pb.directory(new File("C:\\DevWork\\personal\\java\\projects\\wip\\StackOverflow\\HelloWorld\\dist")); 
      pb.redirectError(); 
      try { 
       Process pro = pb.start(); 
       InputConsumer ic = new InputConsumer(pro.getInputStream(), this); 
       System.out.println("...Waiting"); 
       exitCode = pro.waitFor(); 

       ic.join(); 

       System.out.println("Process exited with " + exitCode + "\n"); 

      } catch (Exception e) { 
       System.out.println("sorry" + e); 
      } 
      publish("Process exited with " + exitCode); 
      return exitCode; 
     } 

     @Override 
     public void consume(String value) { 
      publish(value); 
     } 
    } 

    public static class InputConsumer extends Thread { 

     private InputStream is; 
     private Consumer consumer; 

     public InputConsumer(InputStream is, Consumer consumer) { 
      this.is = is; 
      this.consumer = consumer; 
      start(); 
     } 

     @Override 
     public void run() { 
      try { 
       int in = -1; 
       while ((in = is.read()) != -1) { 
//     System.out.print((char) in); 
        consumer.consume(Character.toString((char)in)); 
       } 
      } catch (IOException exp) { 
       exp.printStackTrace(); 
      } 
     } 
    } 
} 
+0

Non ha funzionato per me, come ho detto, penso che abbia a che fare con questo ho reindirizzato l'output della console a un JTextArea. – Ciphor

+0

Non è stato menzionato un 'JTextArea'? Stai eseguendo il processo all'interno dell'EDT? – MadProgrammer

+0

Mi spiace, sì, mi rendo conto che questa è stata la parte cruciale che ha causato il problema come ho commentato in precedenza. E non abbiamo ancora coperto i thread sul mio corso scusa><" – Ciphor

Problemi correlati