【168】Java调用EXE并利用多线程接收EXE的输出流

2023-11-10

代码一共分两个类,分别是 CmdInputStreamRunnable 和 CmdUtils

CmdInputStreamRunnable.java

import java.io.*;

/**
 * @author 张超
 * 操作系统执行命令时会有输出,这些输出会被Java当作输入进行读取。
 * 本类启动线程来读取操作系统执行命令时的输出,避免出现JVM线程卡死,但命令本身正常的情况。
 */
public class CmdInputStreamRunnable implements Runnable {
    private StringBuffer stringBuffer;
    private InputStream inputStream;

    public CmdInputStreamRunnable(StringBuffer stringBuffer, InputStream inputStream) {
        this.stringBuffer = stringBuffer;
        this.inputStream = inputStream;
    }

    @Override
    public void run() {
        BufferedReader bufrIn = null;
        try {
            bufrIn = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            // 读取输出
            String line = null;
            while ((line = bufrIn.readLine()) != null) {
                stringBuffer.append(line).append('\n');
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != bufrIn) {
                    bufrIn.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

CmdUtils.java


import java.io.*;

/**
 * @author 张超
 */
public class CmdUtils {
    
    /**
     * 执行命令,返回系统输出的字符串
     *
     * @param cmd 要执行的执行命令。对于exe等可执行程序,建议在命令中写好绝对路径,或者在操作系统中设置好环境变量。
     * @return 系统执行命令后输出的字符串
     */
    public static String exec(String cmd) {
        // 存放OS执行命令时的输出(对Java来说是输入)
        StringBuffer result = new StringBuffer();

        Process process = null;

        try {
            // 执行命令, 返回一个子进程对象(命令在子进程中执行)
            process = Runtime.getRuntime().exec(cmd, null, null);

            CmdInputStreamRunnable processInput = new CmdInputStreamRunnable(result, process.getInputStream());
            CmdInputStreamRunnable processError = new CmdInputStreamRunnable(result, process.getErrorStream());

            new Thread(processInput).start();
            new Thread(processError).start();

            // 方法阻塞, 等待命令执行完成(成功会返回0)
            process.waitFor();

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 销毁子进程
            if (process != null) {
                process.destroy();
            }
        }

        // 返回执行结果
        return result.toString();
    }

    /**
     * 执行命令,返回系统输出的字符串
     *
     * @param cmd 要执行的执行命令。对于exe等可执行程序,建议在命令中写好绝对路径,或者在操作系统中设置好环境变量。
     * @param timeout 子进程的存活时间,子进程超时后
     * @param unit 过期时间的时间单位
     * @return 系统执行命令后输出的字符串
     */
    public static String exec(String cmd, long timeout, TimeUnit unit) {
        // 存放OS执行命令时的输出(对Java来说是输入)
        StringBuffer result = new StringBuffer();

        Process process = null;

        try {
            // 执行命令, 返回一个子进程对象(命令在子进程中执行)
            process = Runtime.getRuntime().exec(cmd, null, null);

            CmdInputStreamRunnable processInput = new CmdInputStreamRunnable(result, process.getInputStream());
            CmdInputStreamRunnable processError = new CmdInputStreamRunnable(result, process.getErrorStream());

            new Thread(processInput).start();
            new Thread(processError).start();


            // 方法阻塞, 等待命令执行完成(成功会返回0)
            process.waitFor(timeout, unit);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            logger.error("CmdUtils.exec   ", e);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("CmdUtils.exec   ", e);
        } catch (InterruptedException e) {
            e.printStackTrace();
            logger.error("CmdUtils.exec   ", e);
        } finally {
            // 销毁子进程
            if (process != null) {
                process.destroy();
            }
        }

        // 返回执行结果
        return result.toString();
    }

}

使用方法:

String liveUrl = "...";  // 根据具体业务确定直播流地址
String diskPath = "D:\\yourfolder\\a.mp4";
String cmdStr = "ffmpeg -timeout 9000000 -y  -i " + liveUrl + " -vcodec libx264 -f mp4 -t 10 " + diskPath;
String cmdResult = CmdUtils.exec(cmdStr,10, TimeUnit.MINUTES);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【168】Java调用EXE并利用多线程接收EXE的输出流 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Spring Batch 多线程 - 如何使每个线程读取唯一的记录?

    这个问题在很多论坛上都被问过很多次了 但我没有看到适合我的答案 我正在尝试在我的 Spring Batch 实现中实现多线程步骤 有一个包含 100k 条记录的临时表 想要在 10 个线程中处理它 每个线程的提交间隔为 300 因此在任何时
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • 滑动窗口系列4-Leetcode322题零钱兑换-限制张数-暴力递归到动态规划再到滑动窗口

    这个题目是Leecode322的变种 322原题如下 我们这里的变化是把硬币变成可以重复的 并且只有coins数组中给出的这么多的金币 也就是说有数量限制 package dataStructure leecode practice imp
  • 虚拟现实下的手势识别综述

    虚拟现实下的手势识别综述 目录 虚拟现实下的手势识别综述 摘要 关键词 1 引言 2 国内外研究现状 3 手势识别的关键技术 3 1手势分割 3 2手势建模 3 3手势识别 3 4特征提取 4 存在的问题及发展趋势 5 结论 参考文献 摘要
  • js list 根据id 取不重复的数据,出现重复的完全剔除

    可以使用Set数据结构来实现根据id取不重复的数据 并剔除重复的数据 假设有一个包含多个对象的数组arr 每个对象都有一个id属性 你可以按照以下步骤进行操作 创建一个空的Set对象 用于存储不重复的id 使用forEach 方法遍历数组a
  • QT入门Buttons之QPushButton

    目录 一 界面布局介绍 1 布局器中的位置及使用 2 控件的界面属性 3 常用基本属性介绍 3 1控件名称 3 2控件大小属性 3 3按钮上的文字设置 3 4设置按钮的样式 二 属性功能介绍 1 常用方法介绍 2 基本信号介绍 三 Demo
  • servlet 会话_在Servlet中管理会话

    servlet 会话 We all know that HTTP is a stateless protocol All requests and responses are independent But sometimes you ne
  • CentOS7创建新用户

    使用root账号登录 输入新增用户的命令 XXX 指定自己新增的用户名 root localhost adduser XXX 给新增的用户名设置密码 XXX 为刚才自己设置的用户名 root localhost passwd XXX 给新用
  • PHP学习线路图

    PHP学习线路图 PHP教程 PHP教程 PHP简介 PHP环境设置 PHP语法概述 PHP变量类型 PHP常量类型 PHP运算符类型 PHP 条件语句 PHP循环语句 PHP数组 PHP字符串操作 PHP Web概念 PHP的GET和PO
  • Java链表的基本使用

    链表是一种根据元素节点逻辑关系排列起来的一种数据结构 利用链表可以保存多个数据 这一点类似于数组的概念 但是数组本身有一个缺点 数组的长度固定 不可改变 在长度固定的情况下首选的肯定是数组 但是在现实的开发之中往往要保存的内容长度是不确定的
  • 2022计算机软件毕业设计大全

    springboot快递代拿系统 6630 电竞选手管理系统 SSM MySQL 6629 自习室预约网站 SSM MySQL 6626 眼镜销售系统 SSM MySQL 6620 基于Java的学生管理系统 IDEA SSM MySQL
  • Centos7 增加/修改SSH连接端口

    Centos7 增加 修改SSH连接端口 1 修改配置文件 2 如果你关闭了SELinux 可以忽略这一步 3 防火墙开放22345端口 4 重启SSH服务和防火墙 最好也重启下服务器 1 修改配置文件 vim etc ssh sshd c
  • typescript变量声明入门 泛型 interface 可索引接口 type

    最近面试了好多人 简历都写熟练使用TypeScript 可是聊下来发现声明复杂一点的变量只会any 简直就是来搞笑的 TypeScript 是 JavaScript 的超集 扩展了 JavaScript 的语法 TypeScript中为了使
  • maven setting

    Maven Phases Although hardly a comprehensive list these are the most common default lifecycle phases executed validate v
  • 【机器学习代码例】用BP神经网络做预测

    机器学习算法 源码下载链接 导入包 import numpy as np import matplotlib pyplot as plt import pandas as pd 定义激活函数 激活函数 def tanh x return n
  • jeecg boot MybatisInterceptor 的使用笔记

    目前使用的旧版本是2 0 2 更新了新版本2 2 1 sql UPDATE tablename set update time updateTimeNew where ID id and update time updateTime 使用中
  • 【CSS】CSS餐厅小游戏练习1~32关的参考答案

    链接 CSS3餐厅练习 玩法 利用各种选择器选中抖动的物体即可通关 1 Type Selector 元素选择器 元素选择器 作用 根据标签名来选中指定的元素 语法 标签名 例子 p h1 div plate 2 Type Selector
  • 07 - 日志服务器的搭建与攻击

    目录 1 项目环境 2 拓扑图 3 思路 4 配置GW CentOS 7 4 1 配置ens33 4 2 配置ens32 4 3 配置ens34 5 配置Server CentOS 7 1804 7 配置Syslog CentOS 7 18
  • webpack4入门笔记——打包模式选择

    什么是mode webpack4增加了mode配置项 这样会做一些默认的工作 一定程度上解决了webpacke配置复杂的弊端 语法 mode development production 复制代码 不配置默认是production 这是2种
  • Python中最小堆结构的heapq模块

    堆是非线性的树形的数据结构 完全二叉树 有两种堆 最大堆与最小堆 heapq库中的堆默认是最小堆 最大堆 树中各个父节点的值总是大于或等于任何一个子节点的值 最小堆 树中各个父节点的值总是小于或等于任何一个子节点的值 我们一般使用二叉堆来实
  • 用python送父亲节祝福,父亲节:程序员硬核示爱,“爸”气告白!

    转载来自51cto https blog 51cto com 15127557 2665130 转眼 已至6月第三周了 2020年即将过去一半 2020年06月21日 星期日 庚子年 鼠年 五月初一 也就是明天 这一天也是父亲节 父亲节 F
  • 【168】Java调用EXE并利用多线程接收EXE的输出流

    代码一共分两个类 分别是 CmdInputStreamRunnable 和 CmdUtils CmdInputStreamRunnable java import java io author 张超 操作系统执行命令时会有输出 这些输出会被