2016-12-21 4 views
2

Ich arbeite an einem neuen Projekt. Ich versuche Befehle über Linux an einen externen Computer (Linux) zu senden. Ich benutze Jsch, um eine Shell-Verbindung zu erstellen. Ich setze Shell-Eingabe und Ausgabe auf System.out und System.in.Wie kann ich System.in zu JavaFX TextField umleiten?

((ChannelShell)channel).setInputStream(System.in); 
((ChannelShell)channel).setOutputStream(System.out); 

Es funktioniert in der Konsole! Aber ich muss es von der javafx GUI App fernsteuern. Ich habe bereits gelöst Umleiten von System.out zu TextArea-:

public void redirectOutputStream() { 
     OutputStream out = new OutputStream() { 

      private final StringBuilder sb = new StringBuilder(); 

      @Override 
      public void write(int b) throws IOException { 
       if (b == '\r') { 
        return; 
       } 

       if (b == '\n') { 
        final String tmp = sb.toString() + "\n"; 
        text.add(tmp); 
        updateText(text); 
        sb.setLength(0); 
       } else { 
        sb.append((char) b); 
       } 
      } 
     }; 

     System.setOut(new PrintStream(out, true)); 
     // System.setErr(new PrintStream(out, true)); 
    } 

Aber jetzt brauche ich auch System.in zu TextField- umleiten, so dass ich etwas in TextField- zu schreiben, drücken Sie die Eingabetaste und durch Shell die schicken externer Computer.

Jede Hilfe wäre zu schätzen. Vielen Dank!

EDIT: Sorry, noch nicht für mich funktioniert :(... Jetzt habe ich dieses Stück Code (ich bin mit javafx):

/** Tmp queue for standard input redirecting */ 
BlockingQueue<Integer> stdInQueue = new LinkedBlockingQueue<>(); 



@Override 
    public void initialize(URL arg0, ResourceBundle arg1) { 
     redirectOutputStream(); 
     redirectInputStream(); 
} 


/** redirects standard System.out to GUI command_window */ 
public void redirectOutputStream() { 
    OutputStream out = new OutputStream() { 

     private final StringBuilder sb = new StringBuilder(); 

     @Override 
     public void write(int b) throws IOException { 
      if (b == '\r') { 
       return; 
      } 
      if (b == '\n') { 
       final String tmp = sb.toString() + "\n"; 
       text.add(tmp); 
       updateText(text); 
       sb.setLength(0); 
      } else { 
       sb.append((char) b); 
      } 
     } 
    }; 
    System.setOut(new PrintStream(out, true)); 
    System.setErr(new PrintStream(out, true)); 
} 

/** redirects standard System.in to GUI command_line */ 
public void redirectInputStream() { 
    InputStream in = new InputStream() { 

     @Override 
     public int read() throws IOException { 
      try { 
       int c = stdInQueue.take().intValue(); 
       return c; 
      } catch (InterruptedException exc) { 
       Thread.currentThread().interrupt(); 
       return -1; 
      } 
     } 
    }; 
    System.setIn(in); 
} 


@FXML 
    void sendButtonPressed(ActionEvent event) { 
     if (!command_line.getText().isEmpty()) { 
      for (char c : command_line.getText().toCharArray()) { 
       System.out.write(new Integer(c)); //display in ListView (output) 
       stdInQueue.add(new Integer(c)); 
      } 
      System.out.write(new Integer('\n')); //display in ListView (output)  
      stdInQueue.add(new Integer('\n')); 
      command_line.clear(); 
     } 
    } 

Das Umleiten des Systems. out und System.err funktioniert einwandfrei.Es wird in javafx ListView angezeigt.Es ist in der ListView Javafx TextField und ich muss einige ssh-Befehl in diese TextField und Redirect schreiben Wenn Sie auf "Enter" drücken oder auf "Send " Taste.

Der Grund, warum ich dies tun muss, ist, dass ich SSH-Kommunikation verwende, die für System.in und System.out festgelegt ist. Es funktioniert vollständig in der Konsole (getestet), aber nicht in meiner GUI-App.

Vielen Dank für weitere Beratung!

+0

Wenn Sie einen InputStream erstellen können, der mit dem Textfeld verknüpft ist, versuchen Sie es mit 'System.setIn (...)'. – Thomas

+0

Sorry, ich weiß nicht, wie ich den Kommentar bearbeiten kann ... Ich habe versucht, System.setIn (new InputStream()) zu verwenden; aber ich war nicht erfolgreich mit dem Überschreiben der "read()" Methode. – Zuzana

Antwort

0

Sie können ein BlockingQueue<Integer> einrichten, um die einzelne Zeichen zu senden, und haben dann den Eingangsstrom von ihm Zeichen nehmen:

BlockingQueue<Integer> stdInQueue = new LinkedBlockingQueue<>(); 

System.setIn(new InputStream() { 

    @Override 
    public int read() throws IOException { 
     try { 
      int c = stdInQueue.take().intValue(); 
      return c; 
     } catch (InterruptedException exc) { 
      Thread.currentThread().interrupt(); 
      return -1 ; 
     } 
    } 
}); 

textField.setOnAction(e -> { 
    for (char c : textField.getText().toCharArray()) { 
     stdInQueue.add(new Integer(c)); 
    } 
    stdInQueue.add(new Integer('\n')); 
    textField.clear(); 
}); 

Hier ist eine kurze Demo: zum Testen wir einrichten nur einen Hintergrund-Thread, liest aus System.in:

import java.io.IOException; 
import java.io.InputStream; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.LinkedBlockingQueue; 

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class StdInFromTextField extends Application { 

    @Override 
    public void start(Stage primaryStage) { 

     TextField textField = new TextField(); 

     BlockingQueue<Integer> stdInQueue = new LinkedBlockingQueue<>(); 

     System.setIn(new InputStream() { 

      @Override 
      public int read() throws IOException { 
       try { 
        int c = stdInQueue.take().intValue(); 
        return c; 
       } catch (InterruptedException exc) { 
        Thread.currentThread().interrupt(); 
        return -1 ; 
       } 
      } 
     }); 

     textField.setOnAction(e -> { 
      for (char c : textField.getText().toCharArray()) { 
       stdInQueue.add(new Integer(c)); 
      } 
      stdInQueue.add(new Integer('\n')); 
      textField.clear(); 
     }); 

     // for testing: 
     Thread readThread = new Thread(() -> { 
      try { 
       int i ; 
       while ((i = System.in.read()) != -1) { 
        System.out.print((char)i); 
       } 
      } catch (IOException exc) { 
       exc.printStackTrace(); 
      } 
     }); 
     readThread.setDaemon(true); 
     readThread.start(); 

     primaryStage.setScene(new Scene(new StackPane(textField), 300, 120)); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

Tut mir leid, funktioniert immer noch nicht für mich ... Kannst du mir meinen Code ansehen? (siehe EDIT) – Zuzana

-1

Ok, ich habe jetzt funktionierenden Code. Das Problem ist, dass ich nicht herausgefunden habe, wie ich System.in umleiten kann (es ist wahrscheinlich unmöglich). Also musste ich Streams direkt vom SSH-Connector umleiten.

Hier ist, wie ich gesetzt Eingang und Ausgang in jsch stream:

public class ToradexSSHCommunicator { 

String user; 
String password; 
String ip; 
int port; 

InputStream fromChannel; 
OutputStream toChannel; 

/** logger for error output feed */ 
private static final Logger LOGGER = Logger.getLogger(ToradexSSHCommunicator.class); 

public ToradexSSHCommunicator(String user, String password, String ip, int port) { 
    this.user = user; 
    this.password = password; 
    this.ip = ip; 
    this.port = port; 
} 

public void startup() { 
    Session session = null; 
    ChannelShell channel = null; 
    boolean isConnected = false; 

    JSch jsch = new JSch(); 
    while (!isConnected) { 
     try { 
      session = jsch.getSession(user, ip, port); 

      session.setPassword(password); 
      session.setConfig("StrictHostKeyChecking", "no"); 

      LOGGER.info("Establishing Toradex Connection..."); 
      session.setTimeout(1000); 
      session.connect(); 
      LOGGER.info("Toradex connection established."); 

      LOGGER.info("Creating Toradex channel..."); 
      channel = (ChannelShell) session.openChannel("shell"); 
      LOGGER.info("Toradex channel created."); 

      fromChannel = channel.getInputStream(); 
      toChannel = channel.getOutputStream(); 

      channel.connect(); 
      isConnected = true; 

     } 
     catch (JSchException e) { 
      LOGGER.error("Toradex connection error.....RECONNECTING", e); 
      session.disconnect(); 
     } 
     catch (IOException e) { 
      LOGGER.error("Toradex connection error.....RECONNECTING", e); 
      session.disconnect(); 
     } 
    } 

} 

public InputStream getFromChannel() { 
    return fromChannel; 
} 

public OutputStream getToChannel() { 
    return toChannel; 
    } 
} 

Und dieser Teil der GUI, die diese Streams verwenden:

@FXML 
private ListView<String> command_window_toradex; 
@FXML 
private TextField command_line; 

private ToradexSSHCommunicator comm; 

private BufferedReader br; 
private BufferedWriter bw; 

@FXML 
    void sendButtonPressed(ActionEvent event) { 
     executor.submit(new Task<Void>() { 

      @Override 
      protected Void call() throws Exception { 
       writeCommand(); 
       return null; 
      } 
     }); 
    } 

/** initialize SSH connection to Toradex and redirect input and output streams to GUI */ 
private void initToradex() { 
    comm = new ToradexSSHCommunicator(GuiConstants.TORADEX_USER, GuiConstants.TORADEX_PASSWORD, 
      GuiConstants.TORADEX_IP_ADDRESS, GuiConstants.TORADEX_PORT); 
    comm.startup(); 
    br = new BufferedReader(new InputStreamReader(comm.getFromChannel())); 
    bw = new BufferedWriter(new OutputStreamWriter(comm.getToChannel())); 
} 

private void writeCommand() throws IOException { 
    if (!command_line.getText().isEmpty()) { 
     String command = command_line.getText(); 
     bw.write(command + '\n'); 
     bw.flush(); 
     command_line.clear(); 
    } 
} 

private void readCommand() throws IOException { 
    String commandLine = null; 
    while (true) { 
     commandLine = br.readLine(); 
     textToradex.add(commandLine); 
    } 
} 

Es funktioniert! Dies ist jetzt der ganze Code, wenn Sie weitere Hilfe benötigen, fragen Sie einfach.

+0

Es tut mir leid ...: -/ – Zuzana

+0

Nun, hier ist meine Lösung. – Zuzana

Verwandte Themen