2017-01-03 5 views
1

Я пытался выполнить системную команду в Java-приложении с использованием Runtime exec и Process. Я сделал простую программу только для демонстрации, а команда example - 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; и записать его в локальный каталог temp.

Таким образом, вместо того, чтобы указывать на какой-то внутренний ресурс, ваша программа должна сначала создать «временную» версию этого двоичного кода; поэтому вы можете вызвать это с помощью ProcessBuilder (это 2017, забудьте о Runtime.exec()); чтобы впоследствии удалить этот временный файл.

+0

Хорошо, любите часть 2017 года. Спасибо! Я все еще новичок в программировании (просто забыл включить его в вопрос). Я поеду за ним. Еще раз спасибо :) –

+0

Для справки: конечно, с помощью ProcessBuilder - это «современный» способ делать такие вещи; но это не влияет на ваш основной вопрос; как я думаю: это не имеет значения, если вы используете Runtime.exec или ProcessBuilder - в конце концов, вы не можете запустить двоичный файл, который существует только как ресурс где-то в вашем пути к классам (завернутый в некоторый JAR-файл). – GhostCat

+0

Да, я понял. Спасибо огромное! :) –

 Смежные вопросы

  • Нет связанных вопросов^_^