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 2022-12-15 14:53:56 +08:00
可能是 java -version 这个命令行的问题吧,你试试其他的呢? 比如 ls -l /
|
2
rqxiao OP @xiaohundun ls -l / 是 inputStream 。。。这是什么道理
|
3
zjb861107 2022-12-15 15:36:51 +08:00 1
|
4
wolfie 2022-12-15 15:37:44 +08:00 1
redirectErrorStream 合并流,然后用 exitValue 判断成功?
|
5
xiaohundun 2022-12-15 15:58:01 +08:00
@rqxiao 不知道哎😮💨有没有可能源码就写错了给输出到标准错误输出里了😂
|
6
ysc3839 2022-12-15 16:08:58 +08:00
感觉是 X-Y Problem https://coolshell.cn/articles/10804.html
你要调用 ffmpeg 的话可以看看 https://github.com/bramp/ffmpeg-cli-wrapper |
7
xiaohundun 2022-12-15 16:24:12 +08:00 1
@rqxiao 仔细看了下 java -h ,发现人家写的很清楚,-version 就是输出到错误流
|
8
xiaohundun 2022-12-15 16:24:45 +08:00
@rqxiao 你可以用 java --version
|
9
superliy 2022-12-15 16:59:03 +08:00
一个线程一个 process ,你用 ffmpeg 转码,多个线程对你没啥影响
|
10
superliy 2022-12-15 17:00:15 +08:00 1
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 2022-12-16 00:53:58 +08:00 1
为了不污染 stdout ,很多非格式化输出都是输出到 stderr ,比如 curl 的实时进度就是输出到 stderr
|