来自 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 那个东西。
我正在创建一个使用服务代理 运行 多个模块的进程。这些模块将在流程结束时 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 那个东西。