如何等待一个进程输出与java模式匹配的行?

3yhwsihp  于 2021-06-30  发布在  Java
关注(0)|答案(0)|浏览(228)

我在用 ProcessBuilder 在java中运行进程。我想让我的程序等待 Process 直到它的输出流有一行匹配给定的模式,或直到一个时间限制超过。
我用 BufferedReader 逐行阅读 Process.getOutputStream 同时将每一行与模式匹配。当存在匹配或进程在任何匹配之前终止时,它工作正常。但是,当进程在给定的时间限制之后不再输出行时 BufferedReader.readLine() 块和线程从 Process.getOutputStream 永远不会完成。
这是我的密码。

private static Timer setTimeout(Runnable runnable, long timeoutMillis) {
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            runnable.run();
            timer.cancel();
        }
    }, timeoutMillis);
    return timer;
}

static CompletableFuture<Process> startProcessAndWaitForMatchedOutput(
        ProcessBuilder processBuilder, String pattern, long waitForMillis) {
    final CompletableFuture<Process> completableFuture = new CompletableFuture<>();

    final Process process;
    try {
        process = processBuilder.start();
    } catch (IOException ex) {
        completableFuture.completeExceptionally(ex);
        return completableFuture;
    }

    final Pattern compiledPattern = Pattern.compile(pattern);

    final Timer timeoutTimer = setTimeout(() -> 
        completableFuture.completeExceptionally(new WaitForTimeExceededException()),
        waitForMillis);

    new Thread(() -> {
        try (InputStream processOutputStream = process.getInputStream();
             InputStreamReader inputStreamReader = new InputStreamReader(processOutputStream);
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {

            String line;
            /* The thread is blocked here. 
            Indeed the code call this method always return because 
            my completableFuture always completes. 
            But the problem is there is a running thread 
            which is a waste of resource. */
            while ((line = bufferedReader.readLine()) != null) {
                if (compiledPattern.matcher(line).matches()) {
                    completableFuture.complete(process);
                    timeoutTimer.cancel();
                    return;
                }
            }

            completableFuture.completeExceptionally(new OutputDidNotMatchException());
            timeoutTimer.cancel();
        } catch (IOException ex) {
            completableFuture.completeExceptionally(ex);
            timeoutTimer.cancel();
        }
    }).start();

    return completableFuture;
}

我的解决方法正确吗?如果没有,是否有一些库可以解决我的问题?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题