2017-01-03 92 views
1

我试图在使用Runtime execProcess的Java应用程序中执行系统命令。我做了一个简单的程序,仅用于演示,示例命令是javac,它仅编译Java程序。使用该应用程序,只需选择要编译的文件,然后选择稍后将保存的输出文件夹。在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 

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

+0

你应该使用ProcessBuilder和相关的类,并且从不使用Runtime :) –

回答

0

那就是不是可能。

您想拨打操作系统,告诉它在某处运行某个可执行文件。

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

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

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

+0

好吧,喜欢2017年的部分。谢谢!我仍然是编程的初学者(只是忘了把它包含在问题中)。我会去寻找它。再次感谢:) –

+0

备案:当然使用ProcessBuilder是做这种事情的“最先进的”方式;但这并不会影响您的核心问题;正如我的想法:如果您使用Runtime.exe或ProcessBuilder,它并没有什么区别 - 最后,您无法运行只存在于类路径中的某个二进制文件(包含在某个JAR文件中)的二进制文件。 – GhostCat

+0

是的,我现在明白了。非常感谢! :) –