最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決使用ProcessBuilder踩到的坑及注意事項

 更新時間:2021年06月08日 15:26:08   作者:monkey_win  
這篇文章主要介紹了解決使用ProcessBuilder踩到的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

使用ProcessBuilder踩到的坑

最近使用ProcessBuilder執(zhí)行命令,命令內(nèi)容正確,但始終報錯命令實行失敗,是因為不熟悉ProcessBuilder用法踩到了坑,記錄一下。

先看一下我模擬出來的錯誤

在這里插入圖片描述

要執(zhí)行的命令:cp -rf /tmp/monkey/a.log /home/monkey/ 簡單的cp命令拷貝一個文件,卻報錯說文件不存在。確認過文件確實存在該目錄下。

在這里插入圖片描述

查看jdk 中,我使用的ProcessBuilder(***) 源碼實現(xiàn)如下,并不是一個單獨的字符串String形式,而是支持多個字符串,同時還有List集合方式。

在這里插入圖片描述

在這里插入圖片描述

于是想到會不會是ProcessBuilderbuilder不支持包含空格的命令。

動手寫了下面的代碼進行測試

public class ProcessBuilderDemo {
    /**
     * 測試processBuilder執(zhí)行cp命令
     * cp /tmp/monkey/a.log /home/monkey/
     * 源路徑    args[1]: /tmp/monkey/a.log
     * 目標路徑  args[2]: /home/monkey/
     * 方法名    args[3]
     * @param args
     */
    public static void main(String[] args) {
        String src = args[0];
        String tag = args[1];
        String method = args.length == 3 ? args[2] : null;
        if (method != null && method.equals("string")) {
            cmdIsString(src, tag);
        } else {
            cmdIsListOrArray(src, tag);
        }
    }
    /**
     * 執(zhí)行命令,命令用拼接成一個字符串形式(會包含空格)
     * @param src 源路徑
     * @param tag 目標路徑
     */
    private static void cmdIsString(String src, String tag) {
        String cmd = "cp";
        cmd = cmd + " -rf" + " " + src + " " + tag;
        System.out.println("command is: " + cmd);
        ProcessBuilder builder = new ProcessBuilder(cmd);
        try {
            Process process = builder.start();
            process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.toString());
        }
    }
    /**
     * 執(zhí)行命令,命令各個部分拼接成一個數(shù)組或者ArrayList集合
     * 該方法采用數(shù)組實現(xiàn)
     * @param src 源路徑
     * @param tag 目標路徑
     */
    private static void cmdIsListOrArray(String src, String tag) {
        String cmd = "cp";
        // 命令的各個部分組成一個字符串數(shù)組,用該數(shù)組創(chuàng)建ProcessBuilder對象
        String[] cmds = new String[] {cmd, "-rf", src, tag};
        ProcessBuilder builder = new ProcessBuilder(cmds);
        try {
            Process process = builder.start();
            process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.toString());
        }
    }
}

果然如我所猜想的一樣:包含有空格的命令執(zhí)行會報錯。

以下是cmdIsListOrArray方法,將命令的內(nèi)容組成字符串的形式執(zhí)行的結(jié)果,而文章第一張圖則是直接當做一條完整命令的執(zhí)行結(jié)果。

在這里插入圖片描述

至于為什么不能好有空格暫時未做深入了解,有帶佬可以釋疑嗎?難道一條完整的命令當做一個字符串它不香嘛?

while(true) {
    伸手黨;
}

使用ProcessBuilder執(zhí)行本地程序的注意事項

錯誤代碼

    public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder("java","-version");
        Process process = processBuilder.start();
        InputStream inputStream = process.getInputStream();
        xxx(inputStream);
    }
  
    private static void xxx(InputStream inputStream) throws IOException {
        BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
        String ss=null;
        while ((ss=input.readLine())!=null){
            System.out.println(ss);
        }
    }

使用ProcessBuilder類帶參執(zhí)行命令容易出現(xiàn)的兩個坑

1、執(zhí)行后沒有任何反映

原因為通過ProcessBuilder運行的參數(shù)還沒有執(zhí)行完畢程序就退出了。

通過if(process.isAlive()){process.waitFor();}可以規(guī)避此問題,但是需要注意waitFor時程序時阻塞的,如果是持續(xù)運行的web項目可以通過開啟子線程來執(zhí)行ProcessBuilder

2、執(zhí)行后沒有任何輸出

最惡心的地方,除了getInputStream外還有一個getErrorStream也可以獲取數(shù)據(jù),而且一般執(zhí)行的程序數(shù)據(jù)都會輸出在getErrorStream中,所以getInputStream無法獲取到數(shù)據(jù)

處理后的代碼

public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder("java","-version");
        processBuilder.redirectErrorStream(true);//將錯誤流中的數(shù)據(jù)合并到輸入流
        Process process = processBuilder.start();
        if(process.isAlive()){
            process.waitFor();
        }
//        InputStream errorStream = process.getErrorStream();
        InputStream inputStream = process.getInputStream();
//        xxx(errorStream);
        xxx(inputStream);
    }
 
    private static void xxx(InputStream inputStream) throws IOException {
        BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
        String ss=null;
        while ((ss=input.readLine())!=null){
            System.out.println(ss);
        }
    }

后續(xù)發(fā)現(xiàn)新的問題,當某個軟件會持續(xù)向流中寫數(shù)據(jù),這時流中數(shù)據(jù)沒有被讀取完畢(流中存在數(shù)據(jù)【測試發(fā)現(xiàn)流中存在數(shù)據(jù)并不是一定會阻塞】),會導致waitFor一直陷入阻塞

上述問題處理后的代碼(正確使用ProcessBuilder的代碼)

 public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder("java","-version");
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
//        通過標準輸入流來拿到正常和錯誤的信息
        InputStream inputStream = process.getInputStream();
        BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
        String ss=null;
        while ((ss=input.readLine())!=null){
            System.out.println(ss);
        }
        process.waitFor();
    }

復現(xiàn)錯誤:

1、某個軟件持續(xù)向流中寫數(shù)據(jù)時,如果流中數(shù)據(jù)未被讀取完畢waitFor一直陷入等待

public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder();
        List<String> meta = new ArrayList<String>();
        meta.add("ffmpeg");
        meta.add("-i");
        meta.add("C:/Users/Lenovo/Desktop/20200801134820261.mp3");
        meta.add("-af");
        meta.add("silencedetect=n=-1dB:d=0.5");
        meta.add("-f");
        meta.add("null");
        meta.add("-");
        processBuilder.command(meta);
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        InputStream inputStream = process.getInputStream();
//        BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
//        String ss=null;
//        while ((ss=input.readLine())!=null){
//            System.out.println(ss);
//        }
        process.waitFor();
        System.out.println("一直阻塞無法執(zhí)行到這一步");
    }

2、通過下面代碼證明上面的觀點:當將流中數(shù)據(jù)讀取完畢后waitFor不會阻塞,可執(zhí)行下一步

public static void main(String[] args) throws IOException, InterruptedException {
    ProcessBuilder processBuilder = new ProcessBuilder();
    List<String> meta = new ArrayList<String>();
    meta.add("ffmpeg");
    meta.add("-i");
    meta.add("C:/Users/Lenovo/Desktop/20200801134820261.mp3");
    meta.add("-af");
    meta.add("silencedetect=n=-1dB:d=0.5");
    meta.add("-f");
    meta.add("null");
    meta.add("-");
    processBuilder.command(meta);
    processBuilder.redirectErrorStream(true);
    Process process = processBuilder.start();
    InputStream inputStream = process.getInputStream();
    BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
    String ss=null;
    while ((ss=input.readLine())!=null){
        System.out.println(ss);
    }
    process.waitFor();
    System.out.println("正常輸出");
}

3、與上面觀點產(chǎn)生矛盾的代碼:下面代碼中的流中仍然存在數(shù)據(jù),但是waitFor并沒有陷入阻塞,推測原因可能是由于ipconfig與ffmpeg不同,不存在 持續(xù)向流中寫數(shù)據(jù)情況,因此waitFor可以正常結(jié)束阻塞

public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder();
        List<String> meta = new ArrayList<String>();
        meta.add("ipconfig");
        processBuilder.command(meta);
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        InputStream inputStream = process.getInputStream();
//        BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
//        String ss=null;
//        while ((ss=input.readLine())!=null){
//            System.out.println(ss);
//        }
        process.waitFor();
        System.out.println("正常輸出");
    }

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • AsyncHttpClient?RequestFilter請求篩選源碼解讀

    AsyncHttpClient?RequestFilter請求篩選源碼解讀

    這篇文章主要為大家介紹了AsyncHttpClient?RequestFilter請求篩選源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Java全面細致講解Cookie與Session及kaptcha驗證碼的使用

    Java全面細致講解Cookie與Session及kaptcha驗證碼的使用

    web開發(fā)階段我們主要是瀏覽器和服務器之間來進行交互。瀏覽器和服務器之間的交互就像人和人之間進行交流一樣,但是對于機器來說,在一次請求之間只是會攜帶著本次請求的數(shù)據(jù)的,但是可能多次請求之間是會有聯(lián)系的,所以提供了會話機制
    2022-06-06
  • Mybatisplus實現(xiàn)JSON處理器的示例代碼

    Mybatisplus實現(xiàn)JSON處理器的示例代碼

    Mybatisplusjson是基于Mybatisplus開發(fā)的一個json工具庫,本文主要介紹了Mybatisplus實現(xiàn)JSON處理器的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • Java之策略模式比較器案例講解

    Java之策略模式比較器案例講解

    這篇文章主要介紹了Java之策略模式比較器案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • java實現(xiàn)投票程序設(shè)計

    java實現(xiàn)投票程序設(shè)計

    這篇文章主要介紹了java實現(xiàn)投票程序設(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-12-12
  • 解決Mybatis-Plus更新方法不更新NULL字段的問題

    解決Mybatis-Plus更新方法不更新NULL字段的問題

    這篇文章主要介紹了解決Mybatis-Plus更新方法不更新NULL字段的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Web三大組件之Filter,Listener和Servlet詳解

    Web三大組件之Filter,Listener和Servlet詳解

    這篇文章主要為大家詳細介紹了Web三大組件之Filter,Listener和Servlet,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 在SpringBoot環(huán)境中使用Mockito進行單元測試的示例詳解

    在SpringBoot環(huán)境中使用Mockito進行單元測試的示例詳解

    Mockito是一個流行的Java?mocking框架,它允許開發(fā)者以簡單直觀的方式創(chuàng)建和使用模擬對象(mocks),Mockito特別適用于在Spring?Boot環(huán)境中進行單元測試,所以本文介紹了在SpringBoot環(huán)境中使用Mockito進行單元測試的示例,需要的朋友可以參考下
    2024-11-11
  • Java 文創(chuàng)商城系統(tǒng)的實現(xiàn)流程

    Java 文創(chuàng)商城系統(tǒng)的實現(xiàn)流程

    讀萬卷書不如行萬里路,只學書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+mysql+maven+tomcat實現(xiàn)一個文創(chuàng)商城系統(tǒng),大家可以在過程中查缺補漏,提升水平
    2021-11-11
  • RabbitMQ消息隊列的目錄結(jié)構(gòu)

    RabbitMQ消息隊列的目錄結(jié)構(gòu)

    這篇文章主要介紹了RabbitMQ消息隊列的目錄結(jié)構(gòu),RabbitMQ?屬于消息中間件,主要用于組件之間的解耦,消息的發(fā)送者無需知道消息使用者的存在,反之亦然,那么用了那么久RabbitMQ,其目錄結(jié)構(gòu)是怎樣的呢,讓我們一起來看一下吧
    2023-08-08

最新評論

望都县| 陵川县| 东莞市| 合肥市| 临海市| 望奎县| 平定县| 安阳市| 浦江县| 天全县| 嵩明县| 兴国县| 华阴市| 读书| 永嘉县| 潼南县| 保定市| 海丰县| 洛南县| 壶关县| 库伦旗| 建湖县| 桐柏县| 岑溪市| 孟津县| 渝北区| 孙吴县| 石林| 聂荣县| 丰都县| 河西区| 唐山市| 富阳市| 伊宁市| 临颍县| 全州县| 探索| 阜阳市| 文登市| 会宁县| 长岛县|