【问题标题】:Display BASH result with Java用 Java 显示 BASH 结果
【发布时间】:2013-10-20 21:42:34
【问题描述】:

我正在尝试在 Java 生成的 shell 中运行 BASH 脚本,然后 使用 JTextArea 显示所述 BASH 脚本的结果。

这是(应该)发生魔法的类。

import java.io.IOException;

public class Bobsors {

public static Mainframe frame;

public static void main(String[] args) {

    frame = new Mainframe();
    frame.start();

    run();

}

public static void run() {

    String[] cmd = new String[]{"/bin/sh", "PATH=~/Desktop/bobsors.sh"};
    try {
        Process process = Runtime.getRuntime().exec(cmd);
        frame.setLog(process);
    } catch (IOException e) {
        e.printStackTrace();
    }



}

}

这是我框架的类。

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextArea;
import javax.swing.JLabel;
import javax.swing.border.TitledBorder;

@SuppressWarnings("serial")
public class Mainframe extends JFrame {

private JPanel contentPane;

public static Mainframe frame;
public static JTextArea log = new JTextArea();

/**
 * Launch the application.
 */
public void start() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                frame = new Mainframe();
                frame.setVisible(true);
                frame.setTitle("Bobsors Java Application.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}



public void setLog(Process process) {
    log.setText(process.toString());
}


/**
 * Create the frame.
 */
public Mainframe() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    JPanel panel = new JPanel();
    panel.setBorder(new TitledBorder(null, "Shell Log", TitledBorder.LEADING, TitledBorder.TOP, null, null));
    panel.setBounds(7, 50, 434, 217);
    contentPane.add(panel);
    panel.setLayout(null);

    log.setBounds(5, 17, 424, 210);
    log.setEditable(false);
    panel.add(log);

    JLabel lblBobsors = new JLabel("Bobsors");
    lblBobsors.setBounds(12, 12, 70, 15);
    contentPane.add(lblBobsors);

    JLabel lblWorksOnLinux = new JLabel("Works on Linux only");
    lblWorksOnLinux.setBounds(12, 26, 203, 15);
    contentPane.add(lblWorksOnLinux);


}
}

运行时唯一显示的是这个 “java.lang.UNIXProcess@509d5bae” 有谁知道如何正确执行此操作?

【问题讨论】:

标签: java swing bash


【解决方案1】:

Process 不会覆盖从 Object 继承的默认 toString() 方法,因此它显示该值。

您可以改为使用getInputStream(),它将返回一个InputStream 对象,您可以将其转换为如下字符串:Read/convert an InputStream to a String

另外不要忘记EDT上的任务(事件调度线程)必须快速完成;如果他们不这样做,未处理的事件会备份并且用户界面变得无响应,因此请确保您使用另一个线程。

【讨论】:

    【解决方案2】:

    您可以使用 InputStreamBufferedReader 来读取输出,类似这样

     InputStream input = process.getInputStream();
     BufferedReader result = new BufferedReader(new InputStreamReader(input));
    

    转换为字符串

     StringBuilder builder = new StringBuilder();
     String line="";
     while((line=result.readLine()) != null){
         builder.append(line + "\n");
     }
    

    请适当添加try & catch

    【讨论】:

    • 现在从这里开始,我将如何正确地将构建器数据(如字符串)显示到 JTextArea 上?
    • 你可以使用builder.toString然后textArea.setText(stringFromBuilder);
    • 令我惊讶的是,第二次运行后它确实奏效了。我不知道为什么它第一次不起作用,但现在它起作用了!感谢您的回答,我会将其标记为立即回答。
    • @user2875269:虽然懒惰没有解决这个问题,但看在上帝的份上,请注意你的线程。如果您尝试在 Swing 事件线程上读取 BufferedReader,您将冻结您的 GUI 程序。出于这个原因,我建议您接受 D 先生的回答而不是这个。
    • 目前我真的很高兴它有效,但是我理解为什么 D 先生的方法更好,我会尽快研究它,如果它安慰你接受他的回答答案。