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

Posted zhangchao19890805

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了168Java调用EXE并利用多线程接收EXE的输出流相关的知识,希望对你有一定的参考价值。

代码一共分两个类,分别是 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);

以上是关于168Java调用EXE并利用多线程接收EXE的输出流的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程-Java多线程概述

Java多线程编程Java多线程技能

168Java调用EXE程序出现阻塞问题的解决方法

使用delphi多线程实现绑定某个EXE的进程并且向它发送键盘鼠标消息的实例。

WPF 利用Process.Start()方法启动指定路径下的exe文件并传递参数接收参数

运行外部 .exe 并从中接收返回值