Выполнить внешнюю программу через терминал в Java - PullRequest
0 голосов
/ 06 января 2012

У меня есть внешняя программа Выдра , которая получает в качестве параметра какое-либо имя файла и создает выходной файл, также указанный в качестве параметра. Так, например, если мой ввод «proof.in» и я хочу, чтобы мой вывод был помещен в файл «proof.out», я выполняю следующую команду в терминале:

otter <proof.in >proof.out

Файл "proof.in" должен находиться в том же файле, что и исполняемый файл выдры.

Проблема в том, что мне нужны эти функции из Java, поэтому в своем коде Java я делаю следующее:

java.lang.Runtime.getRuntime().exec("otter <proof.in >proof.out")

но после этой строки весь пользовательский интерфейс заморожен, ничего не происходит, и выходной файл не создается.

Может кто-нибудь показать мне, где я ошибся ??

Заранее спасибо, Тамаш

Ответы [ 4 ]

5 голосов
/ 06 января 2012

Это нормально: вы пытаетесь запустить команду, обычно выполняемую оболочкой.

Здесь <proof.in и >proof.out воспринимаются как буквальные аргументы исполняемого файла otter, а не как оболочкапереназначения.Но, увидев домашнюю страницу для этого инструмента, он не будет работать: он ожидает данные на stdin, которые обычно предоставляет перенаправление.

Вам нужно запустить эту команду через оболочку, и желательно с помощью компоновщика процессов:

final ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", "otter <proof.in >proof.out");
final Process p = pb.start();

и т. Д. И т. Д.

Конечно, вы также должны убедиться, что программа запускается из правильного каталога - к счастью, ProcessBuilder также позволяет вам это делать.

0 голосов
/ 23 марта 2012

Если вы хотите только запустить программу, всегда помните это: Process p=Runtime.getRuntime().exec ("cmd /c dir"); p.waitFor();

0 голосов
/ 06 января 2012

Вот ссылка на другой вопрос с очень подробным ответом о том, как сделать это правильно асинхронно с потоками. Это единственный способ не блокировать ваш основной поток и повесить графический интерфейс.

private class ProcessResultReader extends Thread
{
    final InputStream is;
    final String type;
    final StringBuilder sb;

    ProcessResultReader(@Nonnull final InputStream is, @Nonnull String type)
    {
        this.is = is;
        this.type = type;
        this.sb = new StringBuilder();
    }

    public void run()
    {
        try
        {
            final InputStreamReader isr = new InputStreamReader(is);
            final BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null)
            {
                this.sb.append(line).append("\n");
            }
        }
        catch (final IOException ioe)
        {
            System.err.println(ioe.getMessage());
            throw new RuntimeException(ioe);
        }
    }

    @Override
    public String toString()
    {
        return this.sb.toString();
    }
}

тогда вы используете вышеупомянутый класс, как так

try
{
    final Process p = Runtime.getRuntime().exec(String.format("cmd /c %s", query));
    final ProcessResultReader stderr = new ProcessResultReader(p.getErrorStream(), "STDERR");
    final ProcessResultReader stdout = new ProcessResultReader(p.getInputStream(), "STDOUT");
    stderr.start();
    stdout.start();
    final int exitValue = p.waitFor();
    if (exitValue == 0)
    {
        System.out.print(stdout.toString());
    }
    else
    {
        System.err.print(stderr.toString());
    }
}
catch (final IOException e)
{
    throw new RuntimeException(e);
}
catch (final InterruptedException e)
{
    throw new RuntimeException(e);
}
0 голосов
/ 06 января 2012

Вы могли видеть, что происходит, когда выполняете команду:

   try {
        Process p=Runtime.getRuntime().exec ("cmd /c dir");

        InputStream is = p.getInputStream();

        BufferedReader br = new BufferedReader (new InputStreamReader (is));

        String aux = br.readLine();

        while (aux!=null) {
            System.out.println (aux);

            aux = br.readLine();
        }
    } 
    catch (Exception e) {
        e.printStackTrace();
    } 

с этим кодом.

...