在Java应用程序中执行系统命令

时间:2017-01-03 09:22:45

标签: java console

我尝试使用Runtime execProcess在Java应用程序中执行系统命令。我为了演示而制作了一个简单的程序,示例命令是javac,它只是编译Java程序。使用该应用程序,只需选择要编译的文件,然后选择将在以后保存的输出文件夹。

这是完整的程序代码:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    private static JFileChooser jFileChooser1, jFileChooser2;

    public static void main(String[] args) {

        JFrame jFrame = new JFrame();
        jFrame.setSize(238, 62);
        jFrame.setResizable(false);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel jPanel = new JPanel();
        jPanel.setLayout(null);

        jFileChooser1 = new JFileChooser();
        jFileChooser2 = new JFileChooser();


        JButton jButton1 = new JButton("File");
        jButton1.setBounds(1, 1, 70, 25);
        jButton1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                jFileChooser1.setCurrentDirectory(new File(System.getProperty("user.dir")));
                jFileChooser1.showOpenDialog(jFrame);
            }
        });
        jPanel.add(jButton1);


        JButton jButton2 = new JButton("Folder");
        jButton2.setBounds(75, 1, 70, 25);
        jButton2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                jFileChooser2.setCurrentDirectory(new File(System.getProperty("user.dir")));
                jFileChooser2.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                jFileChooser2.showOpenDialog(jFrame);
            }
        });
        jPanel.add(jButton2);


        JButton jButton3 = new JButton("Compile");
        jButton3.setBounds(149, 1, 80, 25);
        jButton3.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                File selectedFile = jFileChooser1.getSelectedFile();
                File selectedFolder = jFileChooser2.getSelectedFile();

                String s = null;

                try {
                    Process p = Runtime.getRuntime().exec("javac -d " +selectedFolder+ " " +selectedFile);

                    BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
                    BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));

                    while ((s = stdInput.readLine()) != null) {
                        System.out.println(s);
                    }

                    while ((s = stdError.readLine()) != null) {
                        System.out.println(s);
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
        jPanel.add(jButton3);


        jFrame.add(jPanel);
        jFrame.setVisible(true);
    }
}

但是在我正在开发的实际应用程序中,我尝试执行的系统命令需要一个二进制程序,我想保留在应用程序(本地资源文件)中。例如,它位于assets包中。因此,要访问资源文件,我使用以下代码:

URL binary = Test.class.getClassLoader().getResource("assets/binary.bin");

该命令的示例用法/语法类似于:

"command -options " +binary+ " " +selectedFile+ " " +selectedFolder+ "

在程序中:

...
try {
    URL binary = Test.class.getClassLoader().getResource("assets/binary.bin");
    Process p = Runtime.getRuntime().exec("command -options " +binary+ " " +selectedFile+ " " +selectedFolder+ ");
    ...
}

但是当我在IDE中尝试时出现错误:

Error: Unable to access jarfile file:/D:/Projects/Java/Test/build/classes/assets/binary.bin

这甚至可能吗?我怎样才能做到这一点?任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

可能。

您想要调用操作系统,告诉它在某处运行某些可执行文件。

但某处必须是操作系统可以访问的内容;换句话说:例如,本地文件系统中存在的东西。

您可以通过从JAR获取二进制文件的内容来解决此问题;并将其写入某个本地临时目录。

因此,您的程序必须首先创建该二进制文件的“临时”版本,而不是指向某个内部资源;所以你可以使用 ProcessBuilder 调用它(它是2017年;忘记Runtime.exec());最后删除该临时文件。