
import java.io.IOException; public class Test { public static void main(String[] args) throws IOException, InterruptedException { String command1 = "java -version"; String command2="/Users/user1/develop/ffmpeg/ffmpeg -i /Users/user1/develop/ffmpeg/input.avi -vflpossa fps=1/5 /Users/user1/develop/ffmpeg/input.avi.%d.jpg"; Process p=Runtime.getRuntime().exec(command1); ProcessHandler.dealStream(p); p.waitFor(); System.out.println("结束了"); } } import lombok.extern.slf4j.Slf4j; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * ref: https://blog.csdn.net/weixin_33690367/article/details/86134029 */ @Slf4j public class ProcessHandler { public static String dealStream(Process process) { StringBuilder builder = new StringBuilder(); if (process == null) { return null; } // 处理 InputStream 的线程 new Thread(() -> { BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; try { while ((line = in.readLine()) = null) { builder.append(line); log.info("input===: " + line); } } catch (IOException e) { e.printStackTrace(); } finally { try { in.close(); } catch (IOException e) { // TODO 处理出错 e.printStackTrace(); } } }).start(); // 处理 ErrorStream 的线程 new Thread(() -> { BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream())); String line; try { while ((line = err.readLine()) != null) { builder.append(line); log.info("错误---: " + line); } } catch (IOException e) { e.printStackTrace(); } finally { try { err.close(); } catch (IOException e) { // TODO 处理出错 e.printStackTrace(); } } }).start(); return builder.toString(); } } 1 )为啥 process 一些正常的输出都在 errorStream 里?现在有一个需求想用 ffmpeg 执行转码,如果转码出错了,是不是应该读取 标准错误输出流里 errorStream 的内容,如果 errorStream 的 StringBuilder 不为空,或者有 'error; 字符串,就可以认为是转码失败了?但现在输出测试下来怎么都在 errorstream 里。。
结束了 14:04:19.433 [Thread-1] INFO com.utils.ProcessHandler - 错误---: java version "1.8.0_291" 14:04:19.436 [Thread-1] INFO com.utils.ProcessHandler - 错误---: Java(TM) SE Runtime Environment (build 1.8.0_291-b10) 14:04:19.436 [Thread-1] INFO com.utils.ProcessHandler - 错误---: Java HotSpot(TM) 64-Bit Server VM (build 25.291-b10, mixed mode) 2 ) process 机制原因会导致死锁,所以需要在 waitfor 方法之前,创建线程用于处理 inputstream 中缓冲区的数据。 不用其他线程清空 process 的缓冲区可以吗。在 process 开始后,单靠主线程读取缓冲的内容,读完了主线程再 waitfor 不可以吗。
1 xiaohundun Dec 15, 2022 可能是 java -version 这个命令行的问题吧,你试试其他的呢? 比如 ls -l / |
2 rqxiao OP @xiaohundun ls -l / 是 inputStream 。。。这是什么道理 |
3 edsion996 Dec 15, 2022 |
4 wolfie Dec 15, 2022 redirectErrorStream 合并流,然后用 exitValue 判断成功? |
5 xiaohundun Dec 15, 2022 @rqxiao 不知道哎有没有可能源码就写错了给输出到标准错误输出里了 |
![]() | 6 ysc3839 Dec 15, 2022 感觉是 X-Y Problem https://coolshell.cn/articles/10804.html 你要调用 ffmpeg 的话可以看看 https://github.com/bramp/ffmpeg-cli-wrapper |
7 xiaohundun Dec 15, 2022 @rqxiao 仔细看了下 java -h ,发现人家写的很清楚,-version 就是输出到错误流 |
8 xiaohundun Dec 15, 2022 @rqxiao 你可以用 java --version |
9 superliy Dec 15, 2022 一个线程一个 process ,你用 ffmpeg 转码,多个线程对你没啥影响 |
10 superliy Dec 15, 2022 ProcessBuilder pb = new ProcessBuilder(generateExecCommand(execCommand.apply(args))); pb.redirectErrorStream(true); try { this.process = pb.start(); BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream())); stdOut.lines().forEach(line -> log.info("{}#{}", name, line)); } catch (IOException e) { log.error("Failed to start process: ", e); } |
11 wangyu17455 Dec 16, 2022 为了不污染 stdout ,很多非格式化输出都是输出到 stderr ,比如 curl 的实时进度就是输出到 stderr |