一、前言

最近在开发的时候,遇到java调用C#exe程序的时候,通过Process执行,一般C#程序都有日志输出,但是通过Java怎么获取呢?这其中又会遇到一些什么问题呢?

想通过C#小程序上传文件到服务器,通过Process执行exe文件,但是上传成功与否,要通过小程序的日志来分析,但怎么获取日志呢?百度了一下,通过字符型输入流就可以,虽然功能实现了,但不知道为什么?

public static boolean uploadFileByFtp(String path) {
    try {
        Process pro = Runtime.getRuntime().exec("cmd /c " + "D:\\tool\\uploadFileByFtp.exe" + " " + path);
        BufferedReader br = new BufferedReader(new InputStreamReader(pro.getInputStream()));
        String line = null;
        String ret = "";
        while ((line = br.readLine()) != null) {
            ret = ret + line + "\n";
        }
        if (ret.toString().contains("success")) {
            return true;
        } else {
            return false;
        }
    } catch (Exception e) {
        log.error("uploadFileByFtp exception:{}", e);
    }
    return false;
}

虽然功能实现了,但感觉缺少点什么?

二、waitFor()

waitFor()函数表示,等待子进程执行结束,或者已手动终止子进程,此方法立即返回,否则出于阻塞状态。

当RunTime对象调用exec方法后,jvm会创建一个子进程,该子进程与jvm建立三个管道连接:标准输入流、标准输出流、标准错误流。假设该子进程不断向标准输入流、标准输出流写数据,而jvm不读取的话,会导致缓冲区塞满而无法继续写数据,最终堵塞在waitFor这里。

问题的关键就是,将缓冲区中的信息读出来,便可以避免线程阻塞问题。

public static boolean uploadFileByFtp2() {
    try {
        String path = "D:tool\\uploadFileByFtp\\log.txt";
        File filePath = new File(path);

        Process pro = Runtime.getRuntime().exec("cmd /c " + "D:\\tool\\uploadFileByFtp.exe" + " " + path);

        pro.waitFor();

        List<String> logs = FileUtils.readLines(new File(path), "UTF-8");
        // 获取最后一行 验证是取得成功
        String str = logs.get(logs.size() - 1);
        if (str.contains("success")) {
            log.info("uploadFileByFtp success");
            return true;
        } else {
            log.warn("uploadFileByFtp fail.");
            return false;
        }
    } catch (Exception e) {
        log.error("uploadFileByFtp exception:{}", e);
        return false;
    }
}

还有一种是获取cmd下的日志,

public static boolean uploadFileByFtp3() {
    Process pro = Runtime.getRuntime().exec("cmd /c " + "D:\\tool\\uploadFileByFtp.exe" + " " + path);
 
    // 标准输入流(必须写在 waitFor 之前)
    String inStr = readInputStream(proc.getInputStream());
    // 标准错误流(必须写在 waitFor 之前)
    String errStr = readInputStream(proc.getErrorStream());
 
    int retCode = proc.waitFor();
    if(retCode == 0){
        System.out.println("文件上传成功");
    }
}
 
/**
*   读取缓冲流inputstream,并返回
*/
public static String readInputStream(InputStream is){
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String s ;
    StringBuilder sb = new StringBuilder();
    while((s=br.readLine())!=null){
        System.out.println(s);
        sb.append(s);
    }
    return sb.toString();
}

 

往期精彩内容:

Java知识体系总结(2021版)

Java多线程基础知识总结(绝对经典)

【全栈最全Java框架总结】SSH、SSM、Springboot

超详细的springBoot学习笔记

常见数据结构与算法整理总结

Java设计模式:23种设计模式全面解析(超级详细)

Java面试题总结(附答案)

本文地址:https://blog.csdn.net/guorui_java/article/details/114003267