2012-10-04 7 views
3

최근에 그래픽으로 디자인 된 Swing 기반 콘솔 프로젝트의 일반 터미널 기능을 구현하려고했습니다. 나는 여기에 어떤 사람들이 이것을 가능하게 한 방법을 좋아하지만, 또 다른 큰 종류의 문제를 발견하게되었습니다. 어떤 사람들은 실질적으로 InpuStreamListener에 대해 말했습니다. 내 작품의 샘플 코드 (거의 정확히 광산,하지만 내 응용 프로그램의 소스 코드가)는 다음과 같습니다응용 프로그램에 전달 된 InputStream 가져 오기 및 사용

// Making an executor 
org.apache.commons.exec.DefaultExecutor exec = new org.apache.commons.exec.DefaultExecutor(); 
// Creating the streams (pretty much ignore this, I just include it as a general idea of the method) 
consoleOutputStream = new ConsoleOutputStream(); 
consoleInputStream = new JTextFieldInputStream(gsc.mainWindow.getConsoleInput().getJTextField()); 
// Stream Handler with the customized streams I use for the process 
org.apache.commons.exec.PumpStreamHandler streamHandler = new org.apache.commons.exec.PumpStreamHandler(consoleOutputStream, consoleOutputStream, consoleInputStream); 
// Setting the handler and finally making command line and executing 
exec.setStreamHandler(streamHandler); 
org.apache.commons.exec.CommandLine commandline = org.apache.commons.exec.CommandLine.parse(String.valueOf(arg)); 
      exec.execute(commandline); 

이제 일이 내가 일반적으로 자바 명령을 통해 자바 응용 프로그램을 실행하려고한다 이 방법을 통해. OutputStream은 정말 잘 작동하고 결함이 전혀 없어 내게 모든 것을 제공하지만 입력이있는 응용 프로그램은 많은 문제를 일으 킵니다. 나는 문제가 System.in, Scanner 클래스, Console 클래스 등의 하드 코딩에 상주합니다. 그래서 여기에 내가 어떤 도움이 필요합니까 (마침내) : InputStream 내 응용 프로그램이나 누군가에게 전달할 수 있습니다. 내가 실제로 외부 Java 응용 프로그램을 실행할 때 사용되는 InputStreamListener을 작성하는 방법을 설명합니다 (예, cmd 또는 터미널 대신 내 인터페이스를 통해 실행합니다. 여기에 도구를 만들려고합니다). 이 작업이 너무 복잡하고 내 편이 많이 필요하거나 일반적으로 불가능한 경우 누군가가 전달 된 InputStream을 얻도록 나를 도울 수 있으므로 실제로 인터페이스에 특정한 응용 프로그램을 작성할 수있는 클래스를 작성할 수 있습니까?

미리 감사 드리며이 전체 텍스트를 읽을 시간을 가졌습니다. :)

+0

'event-dispatch-thread' 태그가 @mKorbel에 의해 편집 된 이유를 알고있는 사람이라면 누구나 설명 할 수 있습니까? 감사! :) –

+0

AWT에 대한 모든 이벤트, Swing GUI는 Event dispatch Tread에서 수행해야합니다. – mKorbel

답변

0

이러한 Apache 라이브러리가 InputStreamOutputStream 인터페이스를 구현한다고 가정하면 PipedInputStreamPipedOutputStream을 사용하여 정보에 액세스 할 수 있습니다. PipedStreams를 사용하는 경우에 대해 생각하고 한 가지 -

import java.awt.event.*; 
import java.io.*; 
import javax.swing.*; 

public class InputRedirection extends Box{ 

    public InputRedirection() { 
     super(BoxLayout.X_AXIS); 

     //Remap input 
     //Create the input stream to be used as standard in 
     final PipedInputStream pisIN = new PipedInputStream(); 
     //Create an end so we can put info into standard in 
     PipedOutputStream posIN = new PipedOutputStream(); 
     //Wrap with a writer (for ease of use) 
     final BufferedWriter standardIn = new BufferedWriter(new OutputStreamWriter(posIN)); 
     //Set standard in to use this stream 
     System.setIn(pisIN); 

     //Connect the pipes 
     try { 
      pisIN.connect(posIN); 
     } catch (IOException e2) { 
      e2.printStackTrace(); 
     }   

     //UI element where we're entering standard in 
     final JTextField field = new JTextField(20); 
     ActionListener sendText = new ActionListener(){ 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       try { 
        //Transfering the text to the Standard Input stream 
        standardIn.append(field.getText()); 
        standardIn.flush(); 
        field.setText(""); 
        field.requestFocus(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      }}; 

     field.addActionListener(sendText); 
     add(field); 

     //Why not - now it looks like a real messaging system 
     JButton button = new JButton("Send"); 
     button.addActionListener(sendText); 
     add(button); 

     //Something using standard in 
     //Prints everything from standard in to standard out. 
     Thread standardInReader = new Thread(new Runnable(){ 

      @Override 
      public void run() { 
       boolean update = false; 
       final StringBuffer s = new StringBuffer(); 
       while(true){ 
        try { 

         BufferedInputStream stream = new BufferedInputStream(System.in); 
         while(stream.available() > 0){ 
          int charCode = stream.read(); 
          s.append(Character.toChars(charCode)); 
          update = true; 
         } 
         if(update){ 
          //Print whatever was retrieved from standard in to standard out. 
          System.out.println(s.toString()); 
          s.delete(0, s.length()); 
          update = false; 
         } 

        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       } 
      }}); 
     standardInReader.start(); 

    } 

    public static void main(String[] args){ 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new InputRedirection()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 

오 : 하나의 스레드가 출력에 기록 할 수있는 단 하나의 입력에서 읽을 수 있습니다 여기에 빠른 예입니다. 그렇지 않으면 펑키 한 문제가 발생합니다 (자세한 내용은 http://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/ 참조).

+0

잘못된 것 : 내'consoleOutputStream'은 이미 작동하는'OutputStream'의 확장이며 내부에서 하드 코딩 된 응용 프로그램의 출력을 인쇄합니다 'System.out'에서 인쇄 할 응용 프로그램. 이 기능은 내 'consoleInputStream' 변수에 들어있는'InputStream' 확장을 위해 역순으로 필요합니다. 기본적으로 InputStream을 사용하여 작업하고 싶습니다. 출력물은 이미 괜찮습니다. 파이핑은 최선의 방법이 아닙니다. 이전에 제안 된 InputStreamListener를 사용하여 수행 할 수 있지만 여전히 내 요구에 맞는 최적의 작업은 아닙니다./ –

+0

Previously is http://stackoverflow.com/a/12669494/1650200이 게시물에 쓰여진 클래스는'consoleInputStream'이 가진 객체의 타입입니다. 필요한 것은이 클래스를 사용하여 모든 Java 응용 프로그램에서 실제로 작동하는 입력 클래스로 작동하는 방법입니다. 내가 이미 다른 자바 애플 리케이션 내에서 자바 애플 리케이션을 실행하고 스레드가 조심하지 않으면 쉽게 엉망이 될 수 있습니다까지 파이핑은 조금 서투른 것처럼 보인다, 그래서 나는 이것도 최적의 솔루션을 더 하나 싶습니다! 어쨌든 고마워요. 그리고 당신의 제안에 감사드립니다! :) –

+0

예 - System.in의 리디렉션은 거의 동일한 방식으로 수행되며 뒤로 만 수행됩니다. 설명하기가 쉬웠 기 때문에 System.out을 사용했습니다. System.in을 사용하여 예제를 업데이트 할 예정입니다. 스레드가 진행되는 한, 파이프는 사용하기가 너무 어렵지 않아서 혼란에 빠지지 않습니다. 나는 이것이 당신에게 문제가 될지 의심 스럽습니다. –

관련 문제