在Java中捕获Perl异常

时间:2014-09-09 05:02:33

标签: java perl

我一直在尝试通过Java运行Perl脚本。我甚至发现脚本是如何做到的,但问题是我希望Perl抛出的异常在Java中返回。

import java.io.IOException;

public class Log {
    public static void main(String[] args) throws IOException {
        Process proc = null;
        try
        {
            proc = Runtime.getRuntime().exec("perl C:\\Users\\myscript.pl");
            int returncode = proc.exitValue();
            System.out.println("Process Executed"+returncode);

        }catch(Exception ae)
        {

            System.out.println("Exception is "+ae.toString());
        }
        finally
        {
            proc.destroy(); 
        }
    }
}

当我尝试运行此代码时,我收到的异常是:

Exception is java.lang.IllegalThreadStateException: process has not exited

有人可以帮助我吗?我做错了什么?

2 个答案:

答案 0 :(得分:2)

您需要在exitValue()之前调用Process.waitFor()。另外,我强烈建议您阅读When Runtime.exec() won't,它有更多有用的信息,可以更加健壮地调用外部流程。

proc.waitFor();  // <======= blocks until process exit

int returncode = proc.exitValue();

System.out.println("Process Executed"+returncode)

Process.waitFor()

的文档
  

如果需要,导致当前线程等待,直到进程   由此Process对象表示已终止。此方法返回   如果子进程已经终止,则立即执行。如果   子进程尚未终止,调用线程将被阻塞   直到子进程退出。

答案 1 :(得分:1)

每当您运行子进程时,需要确保以下两点:

a)父进程应监视子进程。 b)父进程应该等待子进程完成以检查其状态。

要实现第一个目标,您应该强制承诺同时使用子进程输出流和错误流。除此之外,父进程需要等待子进程在获取其退出代码之前完成其执行。

要使用输出和错误流,您可以创建一个可以同时读取这两个流的runnable,并将输出记录到文件中。

class StreamConsumer implements Runnable
{
    private InputStream is;
    private String outputFile;


    StreamConsumer(InputStream is, String outputFile)
    {
        this.is = is;
        this.outputFile = outputFile;
    }

    public void run()
    {
        InputStreamReader isr = null;
        BufferedReader br = null;
        FileOutputStream fos = null;
        BufferedWriter bufferedWriter = null;
        char[] characterBuffer = null;
        try
        {
            characterBuffer = new char[1024];
            isr = new InputStreamReader(is,"UTF-8");
            br = new BufferedReader(isr);
            fos = new FileOutputStream(outputFile);
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(fos,"UTF-8"));
            LOGGER.info("Writing to op file: "+ this.outputFile);
            int readCharacters = -1;
            while ((readCharacters = br.read(characterBuffer,0,1024)) != -1)
            {
                String sw = new String(characterBuffer,0,readCharacters);
                /*
                 * To ignore empty chunks
                 */
                if(sw != null && sw.trim().length() > 0)
                {
                    bufferedWriter.write(sw.toString());
                }
                characterBuffer = new char[1024];
            }
            LOGGER.info("Done Writing to op file: "+ this.outputFile);
        }
        catch (Exception ioe)
          {
            LOGGER.error("IOException ", ioe);
          }
        finally
        {
            if(br != null)
            {
                try {
                    br.close();
                } catch (IOException e) {
                    LOGGER.error("IOException ", e);
                }
            }
            if(bufferedWriter != null)
            {
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    LOGGER.error("IOException ", e);
                }
            }
        }

    }
}

消费使用:

StreamConsumer errorStreamConsumer = new StreamConsumer(proc.getErrorStream(),"errorfilepath");
            StreamConsumer outputStreamConsumer = new StreamConsumer(proc.getInputStream(),"outputFilepath");

执行上述操作将确保子进程永不挂起并由父进程有效监视。

另见:

Process.waitFor(), threads, and InputStreams http://www.javaworld.com/article/2071275/core-javahen-runtime-exec---won-t/core-java/when-runtime-exec---won-t.html

要实现第二个,父进程需要等待子进程完成其执行:

proc.waitFor(); 
  

导致当前线程在必要时等待,直到进程   由此Process对象表示已终止。此方法返回   如果子进程已经终止,则立即执行。如果   子进程尚未终止,调用线程将被阻塞   直到子进程退出。

在您请求子进程返回代码之前,这是必需的。

int returncode = proc.exitValue();