简体   繁体   中英

Java jSch Exec with progress bar and real time output to a JTextArea

I'm developing a program in java to download files directly to my server, for that I'm using jSch to connect via ssh and do a wget command, but i would like to stream the output to a JTextArea, and I've already done that, but it will only print it when the download is finished, and i would like to print it as the output of wget command in real time.

CustomOutputStream code:

public class CustomOutputStream extends OutputStream{
private JTextArea textArea;

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

    @Override
    public void write(int b) throws IOException {
        // redirects data to the text area
        textArea.append(String.valueOf((char) b));
        // scrolls the text area to the end of data
        textArea.setCaretPosition(textArea.getText().length());
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        String s = new String(b,off,len);
        textArea.append(s);
        textArea.setCaretPosition(textArea.getText().length());
    }

    @Override
    public void write(byte[] b) throws IOException {
        this.write(b, 0, b.length);
    }

}

here is the Exec code:

Properties props = new Properties(); 
    props.put("StrictHostKeyChecking", "no");
    int port = 22;

    JSch jsch=new JSch();  

    Session session=jsch.getSession(username, host, 22);
    session.setConfig(props);
    session.setPassword(password);
    session.connect();
    String command =  "cd " + info.downPath + " && printf \"" + downLinks + "\" l> d.txt && wget -i d.txt";
    Channel channel=session.openChannel("exec");
    InputStream in=channel.getInputStream();
    OutputStream out = channel.getOutputStream();
    ((ChannelExec)channel).setCommand(command);
    //((ChannelExec)channel).setErrStream(System.err);
    //((ChannelExec)channel).setOutputStream(System.out);
    ((ChannelExec)channel).setErrStream(new CustomOutputStream(taOutput));
    //((ChannelExec)channel).setOutputStream(new CustomOutputStream(taOutput));
    channel.connect();
    byte[] tmp=new byte[1024];
    while(true){
      while(in.available()>0){
        int i=in.read(tmp, 0, 1024);
        if(i<0)break;
        System.out.print(new String(tmp, 0, i));
      }
      if(channel.isClosed()){
        if(in.available()>0) continue; 
        System.out.println("exit-status: "+channel.getExitStatus());
        break;
      }
      try{Thread.sleep(1000);}catch(Exception ee){}
    }
    channel.disconnect();
    session.disconnect();
    bar.setValue(100);

try{Thread.sleep(1000);}catch(Exception ee){}

Your code is probably executing on the Event Dispatch Thread (EDT) and the Thread.sleep(...) is preventing the GUI from repainting itself until the task is finished executing.

So the solution is to start a separate Thread for the long running task so the EDT is able to respond to events.

An easy way do to this is to use a SwingWorker . Read the section from the Swing tutorial on Concurrency in Swing . The tutorial explains more about the EDT and SwingWorker .

After some help e more search, i just create a new thread the handler the connection.

Here is the example i took: from this link :

one = new Thread() {
public void run() {
    try {
        System.out.println("Does it work?");

        Thread.sleep(1000);

        System.out.println("Nope, it doesnt...again.");
    } catch(InterruptedException v) {
        System.out.println(v);
    }
}  

};

one.start();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM