0

StreamGobblerを使用して外部プログラムからの出力を読み取ります。以前は、ffmpegのstderrからのbig(20〜40文字列)出力を読み取って解析していました。ここで、identify(ImageMagick)のstdout(1つの文字列はすべてプログラムの出力であり、このプログラムは非常に迅速に終了します)から1つの文字列のみを読み取って解析したいと思います。また、動作する場合もありますが、「ストリームが閉じられました」というエラーが発生する場合があります。StreamGobblerにはstreamを操作する時間がないと思います(streamGoblerが作業を行う前にプロセスが終了します)。

以下に、ExecThreadクラスとその使用例を示します。

私の英語でごめんなさい...

    String command =  ffmpegExe.getAbsolutePath()+ " -i \""+ fileName +"\"";
    ExecThread thread = new ExecThread(command);
    thread.setPriority(ExecThread.MIN_PRIORITY);
    thread.start();
    thread.waitFor(DEFAULT_WAIT);

    //reading ffmpeg stderr
    BufferedReader ffmpegErr = thread.getErrBufferedReader();
    String line;

    try
    {
        while((line = ffmpegErr.readLine()) !=null)
//some code



private static class ExecThread extends  Thread
{
    public ExecThread(String command)
    {
        this.command = command;
    }
    @Override
    public void run()
    {

        try
        {
            ExecCommand(command);
            exitVal = process.waitFor();
        }
        catch (Exception e )
        {
            logger.error("Error while executing command: " + command + e.getMessage(),e);
            System.err.println("Error");
            System.exit(1);
        }
    }
    public void waitFor(long millis)
    {
        try
        {
            this.join(millis);
            process.destroy();
        } catch (Exception e)
        {
            logger.error("Error while interupting command: " + command + e.getMessage(), e);
        }

    }


    private  void ExecCommand(String command) throws IOException
    {
        //run command
        Runtime rt = Runtime.getRuntime();
        process = rt.exec(new String[]{shellName,shellOption, command}, null, null);

        //get stderr buffered reader
        StreamGobbler errGobbler = new StreamGobbler(process.getErrorStream());
        StreamGobbler outGobbler = new StreamGobbler(process.getInputStream());

        ErrBufferedReader = new BufferedReader(new InputStreamReader(errGobbler));
        OutBufferedReader = new BufferedReader(new InputStreamReader(outGobbler));

    }
    private BufferedReader ErrBufferedReader;

    public BufferedReader getOutBufferedReader()
    {
        return OutBufferedReader;
    }

    private BufferedReader OutBufferedReader;
    private Process process;
    private String command;
    private int exitVal=-1;

    public BufferedReader getErrBufferedReader()
    {
        return ErrBufferedReader;
    }

    public Process getProcess()
    {
        return process;
    }

    public String getCommand()
    {
        return command;
    }

    public int getExitVal()
    {
        return exitVal;
    }
}
4

2 に答える 2

0

2つの変更をお勧めします。

  1. スレッドを作成する代わりに、 Javaプロセスを使用してください。
  2. 入力、出力、およびエラーストリームを閉じて、プロセスを破棄します。そうしないと、ファイルハンドルのリークが発生します。
于 2013-01-30T18:15:40.780 に答える
0

これは良い決定ではありませんが、うまくいきます。以前はString command = identifyExe.getAbsolutePath() + " \"" + file.getAbsolutePath() + "\""; 今だったString command = "sleep 1 ; " + identifyExe.getAbsolutePath() + " \"" + file.getAbsolutePath() + "\"";

スリープは非常に便利な機能です:-)

しかし、あなたがより良い決定を知っているなら教えてください...

于 2013-01-30T18:50:01.147 に答える