Java process 的一些疑问

2022-12-15 14:13:28 +08:00
 rqxiao
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 不可以吗。

1665 次点击
所在节点    Java
11 条回复
xiaohundun
2022-12-15 14:53:56 +08:00
可能是 java -version 这个命令行的问题吧,你试试其他的呢? 比如 ls -l /
rqxiao
2022-12-15 15:19:18 +08:00
@xiaohundun ls -l / 是 inputStream 。。。这是什么道理
zjb861107
2022-12-15 15:36:51 +08:00
wolfie
2022-12-15 15:37:44 +08:00
redirectErrorStream 合并流,然后用 exitValue 判断成功?
xiaohundun
2022-12-15 15:58:01 +08:00
@rqxiao 不知道哎😮‍💨有没有可能源码就写错了给输出到标准错误输出里了😂
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
xiaohundun
2022-12-15 16:24:12 +08:00
@rqxiao 仔细看了下 java -h ,发现人家写的很清楚,-version 就是输出到错误流
xiaohundun
2022-12-15 16:24:45 +08:00
@rqxiao 你可以用 java --version
superliy
2022-12-15 16:59:03 +08:00
一个线程一个 process ,你用 ffmpeg 转码,多个线程对你没啥影响
superliy
2022-12-15 17:00:15 +08:00
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);
}
wangyu17455
2022-12-16 00:53:58 +08:00
为了不污染 stdout ,很多非格式化输出都是输出到 stderr ,比如 curl 的实时进度就是输出到 stderr

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/902710

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX