欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解決使用ProcessBuilder踩到的坑及注意事項(xiàng)

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

使用ProcessBuilder踩到的坑

最近使用ProcessBuilder執(zhí)行命令,命令內(nèi)容正確,但始終報(bào)錯(cuò)命令實(shí)行失敗,是因?yàn)椴皇煜rocessBuilder用法踩到了坑,記錄一下。

先看一下我模擬出來的錯(cuò)誤

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

在這里插入圖片描述

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

動(dòng)手寫了下面的代碼進(jìn)行測(cè)試

public class ProcessBuilderDemo {
    /**
     * 測(cè)試processBuilder執(zhí)行cp命令
     * cp /tmp/monkey/a.log /home/monkey/
     * 源路徑    args[1]: /tmp/monkey/a.log
     * 目標(biāo)路徑  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í)行命令,命令用拼接成一個(gè)字符串形式(會(huì)包含空格)
     * @param src 源路徑
     * @param tag 目標(biāo)路徑
     */
    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í)行命令,命令各個(gè)部分拼接成一個(gè)數(shù)組或者ArrayList集合
     * 該方法采用數(shù)組實(shí)現(xiàn)
     * @param src 源路徑
     * @param tag 目標(biāo)路徑
     */
    private static void cmdIsListOrArray(String src, String tag) {
        String cmd = "cp";
        // 命令的各個(gè)部分組成一個(gè)字符串?dāng)?shù)組,用該數(shù)組創(chuàng)建ProcessBuilder對(duì)象
        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í)行會(huì)報(bào)錯(cuò)。

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

在這里插入圖片描述

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

while(true) {
    伸手黨;
}

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

錯(cuò)誤代碼

    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)的兩個(gè)坑

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

原因?yàn)橥ㄟ^ProcessBuilder運(yùn)行的參數(shù)還沒有執(zhí)行完畢程序就退出了。

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

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

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

處理后的代碼

public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder("java","-version");
        processBuilder.redirectErrorStream(true);//將錯(cuò)誤流中的數(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)新的問題,當(dāng)某個(gè)軟件會(huì)持續(xù)向流中寫數(shù)據(jù),這時(shí)流中數(shù)據(jù)沒有被讀取完畢(流中存在數(shù)據(jù)【測(cè)試發(fā)現(xiàn)流中存在數(shù)據(jù)并不是一定會(huì)阻塞】),會(huì)導(dǎo)致waitFor一直陷入阻塞

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

 public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder("java","-version");
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
//        通過標(biāo)準(zhǔn)輸入流來拿到正常和錯(cuò)誤的信息
        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();
    }

復(fù)現(xiàn)錯(cuò)誤:

1、某個(gè)軟件持續(xù)向流中寫數(shù)據(jù)時(shí),如果流中數(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、通過下面代碼證明上面的觀點(diǎn):當(dāng)將流中數(shù)據(jù)讀取完畢后waitFor不會(huì)阻塞,可執(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、與上面觀點(diǎn)產(chǎn)生矛盾的代碼:下面代碼中的流中仍然存在數(shù)據(jù),但是waitFor并沒有陷入阻塞,推測(cè)原因可能是由于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("正常輸出");
    }

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

相關(guān)文章

  • 在Java中為日期增加一天的多種方法

    在Java中為日期增加一天的多種方法

    這篇文章主要給大家介紹了關(guān)于如何在Java中為日期增加一天的多種方法,在JAVA業(yè)務(wù)代碼中,經(jīng)常會(huì)遇到通過指定時(shí)間,增加指定天數(shù)的業(yè)務(wù)需求,需要的朋友可以參考下
    2023-07-07
  • Java實(shí)現(xiàn)高效PDF文件傳輸技巧

    Java實(shí)現(xiàn)高效PDF文件傳輸技巧

    你是否曾為PDF文件傳輸?shù)牡托识鄲??現(xiàn)在,有了這份Java實(shí)現(xiàn)高效PDF文件傳輸技巧指南,你將能夠輕松解決這個(gè)問題,我們將分享一些實(shí)用的技巧和最佳實(shí)踐,幫助你優(yōu)化文件傳輸過程,不要錯(cuò)過這個(gè)提高工作效率的機(jī)會(huì),快來閱讀這份指南吧!
    2024-03-03
  • Java IO流之節(jié)點(diǎn)流與字符流的相關(guān)知識(shí)總結(jié)

    Java IO流之節(jié)點(diǎn)流與字符流的相關(guān)知識(shí)總結(jié)

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著Java節(jié)點(diǎn)流與字符流展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Spring Boot jar 啟動(dòng)時(shí)設(shè)置環(huán)境參數(shù)的操作

    Spring Boot jar 啟動(dòng)時(shí)設(shè)置環(huán)境參數(shù)的操作

    這篇文章主要介紹了Spring Boot jar 啟動(dòng)時(shí)設(shè)置環(huán)境參數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • java?引用傳遞的三種類型小結(jié)

    java?引用傳遞的三種類型小結(jié)

    這篇文章主要介紹了java?引用傳遞的三種類型,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • java高級(jí)用法之JNA中使用類型映射

    java高級(jí)用法之JNA中使用類型映射

    JNA中有很多種映射,本文主要介紹了java高級(jí)用法之JNA中使用類型映射,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • java門禁系統(tǒng)面向?qū)ο蟪绦蛟O(shè)計(jì)

    java門禁系統(tǒng)面向?qū)ο蟪绦蛟O(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了java門禁系統(tǒng)面向?qū)ο蟪绦蛟O(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Java 正確地從類路徑中獲取資源

    Java 正確地從類路徑中獲取資源

    Java 有能力從類路徑中查找獲取資源,可將資源放在 CLASSPATH 里,也可打包到 Jar 中。本文將具體講述獲取資源的步驟,感興趣的朋友可以了解下
    2021-05-05
  • "Method?Not?Allowed"405問題分析以及解決方法

    "Method?Not?Allowed"405問題分析以及解決方法

    項(xiàng)目中在提交表單時(shí),提示“HTTP 405”錯(cuò)誤——“Method Not Allowed”這里顯示的是,方法不被允許,下面這篇文章主要給大家介紹了關(guān)于"Method?Not?Allowed"405問題分析以及解決方法的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • 基于java servlet過濾器和監(jiān)聽器(詳解)

    基于java servlet過濾器和監(jiān)聽器(詳解)

    下面小編就為大家?guī)硪黄趈ava servlet過濾器和監(jiān)聽器(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10

最新評(píng)論