Process Builder의 출력을 문자열로 리디렉션하는 방법은 무엇입니까?
다음 코드를 사용하여 프로세스 빌더를 시작합니다. 출력을 String으로 리디렉션하는 방법을 알고 싶습니다.
ProcessBuilder pb = new ProcessBuilder(System.getProperty("user.dir")+"/src/generate_list.sh", filename);
Process p = pb.start();
사용해 ByteArrayOutputStream
보았지만 작동하지 않는 것 같습니다.
로부터 읽기 InputStream
. 다음과 같이 출력을 추가 할 수 있습니다 StringBuilder
.
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ( (line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
Apache Commons IOUtils 를 사용하면 한 줄로 수행 할 수 있습니다.
ProcessBuilder pb = new ProcessBuilder("pwd");
String output = IOUtils.toString(pb.start().getInputStream());
Java 8 예 :
public static String runCommandForOutput(List<String> params) {
ProcessBuilder pb = new ProcessBuilder(params);
Process p;
String result = "";
try {
p = pb.start();
final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringJoiner sj = new StringJoiner(System.getProperty("line.separator"));
reader.lines().iterator().forEachRemaining(sj::add);
result = sj.toString();
p.waitFor();
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
용법:
List<String> params = Arrays.asList("/bin/sh", "-c", "cat /proc/cpuinfo");
String result = runCommandForOutput(params);
이 정확한 코드를 사용하며 한 줄 또는 여러 줄 결과에 대해 잘 작동합니다. 오류 스트림 처리기를 추가 할 수도 있습니다.
다음과 같이 할 수 있습니다.
private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
...
Process p = Runtime.getRuntime().exec(commande);
BufferedReader output = getOutput(p);
BufferedReader error = getError(p);
String ligne = "";
while ((ligne = output.readLine()) != null) {
System.out.println(ligne);
}
while ((ligne = error.readLine()) != null) {
System.out.println(ligne);
}
Java 7 및 8의 경우 다음과 같이 작동합니다.
private String getInputAsString(InputStream is)
{
try(java.util.Scanner s = new java.util.Scanner(is))
{
return s.useDelimiter("\\A").hasNext() ? s.next() : "";
}
}
그런 다음 코드에서 다음을 수행하십시오.
String stdOut = getInputAsString(p.getInputStream());
String stdErr = getInputAsString(p.getErrorStream());
나는 그것을 뻔뻔스럽게 훔쳤다. Process Builder의 출력을 문자열로 리디렉션하는 방법?
.inheritIO();
프로세스 빌더 라인에 추가 하기 만하면 됩니다.
IE :
ProcessBuilder pb = new ProcessBuilder(script.sh).inheritIO();
다른 경우를 처리하려고 시도한 후 (stderr 및 stdout을 모두 처리하고 이들 중 어느 것도 차단하지 않고, 시간 초과 후 프로세스를 종료하고, 슬래시, 따옴표, 특수 문자, 공백 등을 적절히 이스케이프 처리합니다. ....) 포기하고 Apache Commons Exec https를 찾았습니다. : //commons.apache.org/proper/commons-exec/tutorial.html 이 모든 일을 잘 수행하는 것 같습니다.
Java에서 외부 프로세스를 호출해야하는 모든 사람에게 Apache Commons Exec 라이브러리를 다시 발명하는 대신 사용하는 것이 좋습니다.
Java 8에는 String.join 및 System.lineSeparator ()와 결합 할 수있는 멋진 lines () 스트림이 있습니다.
try (BufferedReader outReader = new BufferedReader(new InputStreamReader(p.getInputStream()))
{
return String.join(System.lineSeparator(), outReader.lines().collect(toList()));
\\ OR using jOOλ if you like reduced verbosity
return Seq.seq(outReader.lines()).toString(System.lineSeparator())
}
솔루션
- 이 코드는 질문에 대한 일반적인 솔루션을 실행하는 예제입니다.
Process Builder의 출력을 문자열로 리디렉션하는 방법은 무엇입니까?
- 크레딧은 다양한 명령을 실행하고 출력을 캡처하기 위해 여러 솔루션을 시도한 후 Greg T로 이동합니다. Greg T의 답변에는 특정 솔루션의 본질이 포함되어 있습니다. 일반적인 예가 출력을 캡처하는 동안 여러 요구 사항을 결합하는 사람에게 사용되기를 바랍니다.
- 특정 솔루션을 얻으려면 주석
ProcessBuilder pb = new ProcessBuilder(System.getProperty("user.dir")+"/src/generate_list.sh", filename);
을 제거하고 줄의 주석 을 제거하고 주석 처리하십시오ProcessBuilder processBuilder = new ProcessBuilder(commands);
..
기능성
- 명령을 실행
echo 1
하고 출력을 문자열로 반환 하는 작업 예제입니다 . - 또한 특정 예제에 필요하지 않은 작업 경로 및 환경 변수 설정을 추가하여 삭제할 수 있습니다.
사용 및 확인
- 이 코드를 클래스로 복사하여 붙여넣고 jar로 컴파일하고 실행할 수 있습니다.
- WSL Ubuntu 16.04에서 확인되었습니다.
- 작업 디렉토리 설정은
binaryCommand[0]="touch";
및 을 설정 하고 파일을binaryCommand[1]="1";
다시 컴파일하고 실행하여 확인.jar
합니다.
한계
- 파이프가 가득 차면 ( "너무 큰"출력으로 인해) 코드가 중단됩니다.
암호
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Map;
import java.util.StringJoiner;
public class GenerateOutput {
/**
* This code can execute a command and print the output accompanying that command.
* compile this project into a .jar and run it with for example:
* java -jar readOutputOfCommand.jar
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
boolean answerYes = false; // no yes answer to any command prompts is needed.
// to execute a command with spaces in it in terminal, put them in an array of Strings.
String[] binaryCommand = new String[2];
// write a command that gives a binary output:
binaryCommand[0] = "echo";
binaryCommand[1] = "1";
// pass the commands to a method that executes them
System.out.println("The output of the echo command = "+executeCommands(binaryCommand,answerYes));
}
/**
* This executes the commands in terminal.
* Additionally it sets an environment variable (not necessary for your particular solution)
* Additionally it sets a working path (not necessary for your particular solution)
* @param commandData
* @param ansYes
* @throws Exception
*/
public static String executeCommands(String[] commands,Boolean ansYes) throws Exception {
String capturedCommandOutput = null;
System.out.println("Incoming commandData = "+Arrays.deepToString(commands));
File workingDirectory = new File("/mnt/c/testfolder b/");
// create a ProcessBuilder to execute the commands in
ProcessBuilder processBuilder = new ProcessBuilder(commands);
//ProcessBuilder processBuilder = new ProcessBuilder(System.getProperty("user.dir")+"/src/generate_list.sh", "a");
// this is not necessary but can be used to set an environment variable for the command
processBuilder = setEnvironmentVariable(processBuilder);
// this is not necessary but can be used to set the working directory for the command
processBuilder.directory(workingDirectory);
// execute the actual commands
try {
Process process = processBuilder.start();
// capture the output stream of the command
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringJoiner sj = new StringJoiner(System.getProperty("line.separator"));
reader.lines().iterator().forEachRemaining(sj::add);
capturedCommandOutput = sj.toString();
System.out.println("The output of this command ="+ capturedCommandOutput);
// here you connect the output of your command to any new input, e.g. if you get prompted for `yes`
new Thread(new SyncPipe(process.getErrorStream(), System.err)).start();
new Thread(new SyncPipe(process.getInputStream(), System.out)).start();
PrintWriter stdin = new PrintWriter(process.getOutputStream());
//This is not necessary but can be used to answer yes to being prompted
if (ansYes) {
System.out.println("WITH YES!");
stdin.println("yes");
}
// write any other commands you want here
stdin.close();
// this lets you know whether the command execution led to an error(!=0), or not (=0).
int returnCode = process.waitFor();
System.out.println("Return code = " + returnCode);
} catch (IOException e1) {
e1.printStackTrace();
}
return capturedCommandOutput;
}
/**
* source: https://stackoverflow.com/questions/7369664/using-export-in-java
* @param processBuilder
* @param varName
* @param varContent
* @return
*/
private static ProcessBuilder setEnvironmentVariable(ProcessBuilder processBuilder){
String varName = "variableName";
String varContent = "/mnt/c/testfolder a/";
Map<String, String> env = processBuilder.environment();
System.out.println("Setting environment variable "+varName+"="+varContent);
env.put(varName, varContent);
processBuilder.environment().put(varName, varContent);
return processBuilder;
}
}
class SyncPipe implements Runnable
{
/**
* This class pipes the output of your command to any new input you generated
* with stdin. For example, suppose you run cp /mnt/c/a.txt /mnt/b/
* but for some reason you are prompted: "do you really want to copy there yes/no?
* then you can answer yes since your input is piped to the output of your
* original command. (At least that is my practical interpretation might be wrong.)
* @param istrm
* @param ostrm
*/
public SyncPipe(InputStream istrm, OutputStream ostrm) {
istrm_ = istrm;
ostrm_ = ostrm;
}
public void run() {
try
{
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm_.read(buffer)) != -1; )
{
ostrm_.write(buffer, 0, length);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private final OutputStream ostrm_;
private final InputStream istrm_;
}
현재 자바 (9) , 우리는 마침내 하나의 라이너가 :
ProcessBuilder pb = new ProcessBuilder("pwd");
Process process = pb.start();
String result = new String(process.getInputStream().readAllBytes());
참조 URL : https://stackoverflow.com/questions/16714127/how-to-redirect-process-builders-output-to-a-string
'your programing' 카테고리의 다른 글
Mongo ObjectID에서 생성 된 날짜를 추출하는 방법 (0) | 2020.12.29 |
---|---|
생성자 vals를 지속적으로 복제하지 않고 스칼라 케이스 클래스를 확장합니까? (0) | 2020.12.29 |
오류 SQL Server Management Studio의 잘못된 접두사 또는 접미사 문자 (0) | 2020.12.29 |
Alamofire에서 값을 반환하는 방법 (0) | 2020.12.29 |
숫자 셀 "Poi"에서 텍스트 값을 가져올 수 없습니다. (0) | 2020.12.29 |