Java通過Process執行C# exe程式

2021-02-25 12:00:15

一、前言

最近在開發的時候,遇到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\\LogDataCollector\\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面試題總結(附答案)