简体   繁体   中英

Execute external program through terminal in Java

I have an external program Otter that gets as parameter some filename and creates an output file, also specified as parameter. So for example if my input is "proof.in" and I want my output to be placed in the "proof.out" file, I run the following command in the terminal:

otter <proof.in >proof.out

The "proof.in" file must be in the same file as the otter executable.

The problem is that I need this functionality from Java so in my Java code I do the following:

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

but after this line the whole UI is frozen and nothing happens and no output file is generated.

Could anyone show me where I got it wrong??

Thanks in advance, Tamash

This is normal: you are attempting to launch a command normally issued by a shell.

Here, <proof.in and >proof.out are taken as literal arguments to the otter executable, and not shell redirections. But seeing the home page for this tool, it will not work: it expects data on stdin, which the redirect normally provides.

You need to launch this command via a shell, and preferably using a process builder:

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

etc etc.

You should also ensure, of course, that the program runs from the correct directory -- fortunately, ProcessBuilder also allows you to do that.

Here is a link to another question with a very detailed answer on how to do this correctly in an async way with threads. This is the only way to not block your main thread and hang your GUI.

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();
    }
}

then you use the above class like so

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);
}

If you only want to run the program, do always remember this: Process p=Runtime.getRuntime().exec ("cmd /c dir"); p.waitFor(); Process p=Runtime.getRuntime().exec ("cmd /c dir"); p.waitFor();

You could see what is happening when you execute your command:

   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();
    } 

with this code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM