来自 ProcessBuilder 的进程未将输出定向到字符串

Process from ProcessBuilder not directing output to string

我正在创建一个使用服务代理 运行 多个模块的进程。这些模块将在流程结束时 return 一个字符串,初始服务代理调用将 return 并打印该字符串。但是,我的进程构建器进程没有 returning 我的字符串。我放置了打印语句来告诉我不同​​的模块何时 运行ning 并且它打印了正确的答案但没有 RETURN 它作为服务代理的字符串。

ServiceBroker

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;
import java.util.stream.Collectors;

public class ServiceBrokerTest {
    public static String main(String[] args) throws FileNotFoundException {
        String serviceName = args[0];
        String parmList = args[1];
        try {
            Path filePath = Paths.get("Service.txt");
            String absPath = filePath.toFile().getAbsolutePath();
            File serviceText = new File(absPath);

            Scanner scan = new Scanner(serviceText);
            String[] currentLine = null;
            while (scan.hasNextLine()){
                currentLine = scan.nextLine().split(",");

                if (currentLine[0].equals(serviceName)){
                    ProcessBuilder processCompile = new ProcessBuilder();
                    processCompile.directory(new File(System.getProperty("user.dir")));
                    String[] parmsProcessCompile = {"javac", currentLine[1]};
                    processCompile.command(parmsProcessCompile);

                    Process c = processCompile.inheritIO().start();
                    c.waitFor();
                    c.destroy();

                    ProcessBuilder processRun = new ProcessBuilder();
                    processRun.directory(new File(System.getProperty("user.dir")));
                    String runName = currentLine[1].split("\.")[0];
                    String[] parmsProcessRun = {"java", runName,parmList};
                    processRun.command(parmsProcessRun);
                    Process r = processRun.inheritIO().start();
                    r.waitFor();
                    BufferedReader stdOut = new BufferedReader(new InputStreamReader(r.getInputStream()));
                    String stdOutStr = stdOut.lines().collect(Collectors.joining(System.lineSeparator()));

                    return stdOutStr;
                }
            }
        }
        catch (Exception e){
            String[] temp = new String[]{"English", "703"};
            System.out.println(Error.error(temp));
        }

        return null;
    }


}

翻译

    public class Translate {
    public static void main(String[] args) throws IOException {
        translate(args);
    }
    /**
     *
     * @param args  string array. first index will be the filename, second will be the english word to translate from
     * @return  call to service broker with instructions for error call or text broker call
     */
    public static String translate(String[] args) throws IOException {

        ServiceBrokerTest serviceBroker = new ServiceBrokerTest();

        try {
            String[] argArray = args[0].split(",");
            String filename = argArray[0];
            String englishWord = argArray[1];
            String searchMethod = argArray[2];

            // check if the file exists, if not, call error module
            if (!searchFile(filename)) {
                // call error module and return
                return ServiceBrokerTest.main(new String[] {"Error", "English" + ", 805"});

            }
            //for testing
            System.out.println("process run Trans");
            //-------------------------
            return ServiceBrokerTest.main(new String[]{"TB", filename + "," + englishWord + "," + searchMethod});
        } catch (Exception e) {
            return ServiceBrokerTest.main(new String[] {"Error", "English" + ", 404"});
        }
    }

    /**
     *
     * @param filename  name of file you are searching for
     * @return true if file exists, false if otherwise
     */
    public static boolean searchFile(String filename) {
        File temp = new File(filename);
        return temp.isFile();
    }

}

TextBroker

public class TextBroker {

    public static void main(String[] args) throws FileNotFoundException {
        TB(args);
    }

    /**
     * Creates the file from the fileName that was passed down from the service broker
     */
    public static File fileCreation(String filename) throws FileNotFoundException {
        File input = new File(filename);
        return input;
    }


    /**------------------------------------------------------------------------------------------------
     * Search Method
     * ------------------------------------------------------------------------------------------------
     * Takes the passed parameters parm and searchMethod as well as the file created by fileCreation
     * and parses through the given file in search for the correct or corresponding output.
     * ------------------------------------------------------------------------------------------------
     */
    public static String fileSearch(File file, String parm, String searchMethod) throws FileNotFoundException {
        Scanner fileScan = new Scanner(file);
        String[] currentLine;

        /**
         * If there is a comparison that needs >= or <= then the value has to be converted from a
         * string to an int in order for proper comparison of the values.
         */
        int convertedString = 0;

        /**------------------------------------------------------------------------------------------------
         * Search Blocks
         * ------------------------------------------------------------------------------------------------
         * Each if block works by converting the passed parm if necessary, like for >= or <=,
         * then using a while loop it searches the file, splitting the current line and comparing the
         * first value of the line. If it follows the searchMethod parm then it is correct and is returned
         * by the method as a string.
         * ------------------------------------------------------------------------------------------------
         */
        if (searchMethod.equals("<=")){
            convertedString = Integer.parseInt(parm);
            while (fileScan.hasNextLine()){
                currentLine = fileScan.nextLine().split(",");

                if (convertedString <= Integer.parseInt(currentLine[0]) ){
                    System.out.println(currentLine[1]);
                    return currentLine[1];
                }
            }
        }
        else if (searchMethod.equals(">=")){
            convertedString = Integer.parseInt(parm);
            while (fileScan.hasNextLine()){
                currentLine = fileScan.nextLine().split(",");

                if (convertedString <= Integer.parseInt(currentLine[0]) ){
                    System.out.println(currentLine[1]);
                    return currentLine[1];
                }
            }
        }
        else if (searchMethod.equals("=")){
            while (fileScan.hasNextLine()){
                currentLine = fileScan.nextLine().split(",");

                if (currentLine[0].equals(parm)){
                    System.out.println(currentLine[1]);
                    return currentLine[1];
                }
            }
        }

        return null;
    }

    /**
     * The parameters are recieved via an array of strings as args which are assigned variables
     * and passed to the required methods fileCreation and fileSearch.
     * This is in a try catch block so that a fileNotFound is caught and triggers an error call
     * or any other error is caught.
     */
    public static String TB(String[] args) throws FileNotFoundException {
        System.out.println("Process run TB");
        try {
            String[] splitArgs = args[0].split(",");
            String fileName = splitArgs[0];
            String parm = splitArgs[1];
            String searchMethod = splitArgs[2];
            String returnString = fileSearch(fileCreation(fileName),parm, searchMethod);
            return returnString;
        } catch (Exception e) {
            ServiceBrokerTest serviceBroker = new ServiceBrokerTest();
            return serviceBroker.main(new String[] {"Error", "English" + ", 404"});
        }

    }
}

SB 被赋予参数 {"Trans, "german.txt,dog,="},它将 [1] 字符串传递给翻译模块,因此 trans,将参数传递给 TextBroker谁 return 是正确的翻译词。我基本上需要从 TextBroker 将这个词返回到初始服务代理调用并打印。我无法从 Text Broker 打印它,我们需要将它传回生产线。我已经尝试了整个示例线程并且无法让我的 SB return 除了 null 之外的任何东西,即使我的打印语句表明子进程正在到达 returning 字符串的正确点。也许我'我缺少一些简单的东西,但我看不出有什么问题。如果您需要,我可以为 运行ning 提供更多文件,请告诉我。

感谢您的帮助。

您在进程构建器代码中犯了多个错误;您需要先修复它们,然后才能正常工作。

inheritIO() 字面意思是:忘记 .getInputStream() 和重定向以及所有爵士乐,只继承 java 过程本身的标准 in/out/err。你特别想要的,所以摆脱它。

但这还不够。

然后,您首先调用.waitFor(),然后打开输入流。那是行不通的 - 一旦进程终止,您就无法获得输入流。

你需要启动进程,然后读取数据,然后如果必须的话你可以等待。

这是我的一个项目中的一些示例代码:

private static <E extends Throwable> String exec0(String description, Function<String, E> exceptionFactory, String... args) throws E {

    Process process; try {
        process = new ProcessBuilder(args).redirectErrorStream(true).start();
    } catch (IOException e) {
        throw rethrow(e, "Cannot execute " + description, exceptionFactory);
    }
    
    String output; try {
        @Cleanup var in = process.getInputStream();
        output = new String(in.readAllBytes(), StandardCharsets.US_ASCII);
    } catch (IOException e) {
        throw rethrow(e, "Cannot stream results of " + description, exceptionFactory);
    }
    
    int v; try {
        v = process.waitFor();
    } catch (InterruptedException e) {
        throw rethrow(e, "Executing " + description + " interrupted", exceptionFactory);
    }
    
    if (v != 0) throw exceptionFactory.apply(description + " returned with error code " + v + ": " + output);
    return output;
}

private static <E extends Throwable> E rethrow(Throwable source, String prefix, Function<String, E> exceptionFactory) {

    String msg = source.getMessage() == null ? prefix : (prefix + ": " + source.getMessage());
    E ex = exceptionFactory.apply(msg);
    if (source.getCause() != null) ex.initCause(source.getCause());
    ex.setStackTrace(source.getStackTrace());
    return ex;
}

它做了一些花哨的工作让你自动为你的 API 设计抛出适当的异常(通常 'I run an app on the host OS' 应该是一个实现细节,因此 ProcessBuilder 抛出的特定异常不是适合盲目传递;他们需要根据您的 API.

进行重述

如果你不在意,你可以轻松撕掉它。

关键部分是打开输入流首先(直到之后才调用waitFor),并读出所有字节。 in.readAllBytes() 是一种相当方便的方法。

注意:@Cleanup 是 lombok 清理。如果你不使用它,那么使用 try (var in = x.getInputStream()) { ... } - 你需要 safe-close 那个东西。