Изменение рабочего каталога команды из java

Мне нужно выполнить .exe файл из функции в одном из пакетов, которые у меня есть в моем проекте java. теперь рабочий каталог представляет собой корневую директорию проекта для java, но файл .exe в подкаталогах моего проекта. вот как организован проект:

ROOT_DIR
|.......->com
|         |......->somepackage
|                 |.........->callerClass.java
|
|.......->resource
         |........->external.exe

Сначала я попытался запустить файл .exe прямо через:

String command = "resources\\external.exe  -i input -o putpot";
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command);

но проблема заключается в внешнем .exe, необходимо получить доступ к некоторым файлам в его собственном каталоге и держать в курсе, что корневой каталог является его каталогом. Я даже пытался использовать .bat файл для решения проблемы, но эта же проблема возникает:

Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "resources\\helper.bat"});

а файл .bat находится в том же каталоге, что и файл .exe, но такая же проблема возникает. вот содержимое файла .bat:

@echo off
echo starting process...

external.exe -i input -o output

pause

даже если я перемещаю файл .bat в root и исправляю его содержимое, проблема не исчезает. plz plz plz help

Ответ 1

Чтобы реализовать это, вы можете использовать класс ProcessBuilder, вот как это будет выглядеть:

File pathToExecutable = new File( "resources/external.exe" );
ProcessBuilder builder = new ProcessBuilder( pathToExecutable.getAbsolutePath(), "-i", "input", "-o", "output");
builder.directory( new File( "resources" ).getAbsoluteFile() ); // this is where you set the root folder for the executable to run with
builder.redirectErrorStream(true);
Process process =  builder.start();

Scanner s = new Scanner(process.getInputStream());
StringBuilder text = new StringBuilder();
while (s.hasNextLine()) {
  text.append(s.nextLine());
  text.append("\n");
}
s.close();

int result = process.waitFor();

System.out.printf( "Process exited with result %d and output %s%n", result, text );

Это довольно куча кода, но дает вам еще больший контроль над тем, как этот процесс будет запущен.

Ответ 2

Используйте эту форму метода exec, чтобы указать рабочий каталог

public Process exec(String[] cmdarray,
                    String[] envp,
                    File dir)
             throws IOException

Рабочий каталог является третьим аргументом. Вы можете передать null для envp, если вам не нужно устанавливать какую-либо специальную среду.

Там также этот удобный метод:

public Process exec(String command,
                    String[] envp,
                    File dir)
             throws IOException

... где вы указываете команду в одной строке (она просто превращается в массив для вас, см. документы для подробностей).

Ответ 3

У меня возникла такая же проблема в моем проекте, я попробовал эти решения о ProcessBuilder.directory(myDir) и методе exec из Runtime, и все мои лотки не удались..
Мне кажется, что Runtime имеют ограниченные привилегии только для рабочего каталога и его подкаталогов.
 
Поэтому мое решение очень быстро, но работает очень хорошо.
Я создаю временный файл .bat в "runtime" в рабочем каталоге.
Этот файл включал две строки команд:
1. Перейдите в нужный каталог (команда cd).
2. Сделайте нужную команду.
Я вызываю exec из Runtime с моим временным файлом .bat как команду.
Это работает для меня очень хорошо!