Read from the InputStream. You can append the output to a 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();
Answer from Reimeus on Stack OverflowRead from the InputStream. You can append the output to a 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();
As of Java 9, we finally have a one liner:
ProcessBuilder pb = new ProcessBuilder("pwd");
Process process = pb.start();
String result = new String(process.getInputStream().readAllBytes());
Exception in thread "main" java.io.IOException: The pipe has been ended
This means the process you have started has died. I suggest you read the output to see why. e.g. did it give you an error.
Is there a reason you are using DataInputStream to read a simple text file? From the Java documentation
A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way
It's possible that the way you are reading the file causes an EOF to be sent to the outputstream causing the pipe to end before it gets to your string.
You requirements seems to be to read the file simply to append to it before passing it on to the wkhtmltoimage process.
You're also missing a statement to close the outputstream to the process. This will cause the process to wait (hang) until it gets an EOF from the input stream, which would be never.
I'd recommend using a BufferedReader instead, and writing it directly to the outputstream before appending your additional string. Then call close() to close the stream.
ProcessBuilder pb = new ProcessBuilder(full_path, " - ", image_save_path);
pb.redirectErrorStream(true);
Process process = null;
try {
process = pb.start();
} catch (IOException e) {
System.out.println("Couldn't start the process.");
e.printStackTrace();
}
System.out.println("reading");
try {
if (process != null) {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader inputFile = new BufferedReader(new InputStreamReader(new FileInputStream(currentDirectory+"\\bin\\template.txt")));
String currInputLine = null;
while((currInputLine = inputFile.readLine()) != null) {
bw.write(currInputLine);
bw.newLine();
}
bw.write("<body><div id='chartContainer'><small>Loading chart...</small></div></body></html>");
bw.newLine();
bw.close();
}
} catch (IOException e) {
System.out.println("Either couldn't read from the template file or couldn't write to the OutputStream.");
e.printStackTrace();
}
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String currLine = null;
try {
while((currLine = br.readLine()) != null) {
System.out.println(currLine);
}
} catch (IOException e) {
System.out.println("Couldn't read the output.");
e.printStackTrace();
}
The issue here is that /bin/cat does not actually write to files, it merely writes to standard out. The output redirection >/tmp/receive.dat is actually performed by the shell, but you are bypassing the shell by invoking cat in this manner.
If what you are trying to achieve is merely an OutputStream that writes to a file, then doing that via standard java I/O (e.g., FileOutputStream and friends) is what you want. It is also cross-platform (i.e., Windows-friendly), unlike anything that depends on the shell.
Regarding the comment about not being able to merely write to standard out from java because of subprocesses - any subprocess you invoke can inherit standard out from their parent process (the java process - look at ProcessBuilder.Redirect.INHERIT). So even if you are invoking subprocesses from java, redirecting all the output to a file should still work in the same way as your initial example (where the java program replaces the echo command).
You probably want ProcessBuilder#redirectOutput(File), as the > functionality is not of cat, rather what is calling cat (in our sense, the process builder).
The Process OutputStream (our point of view) is the STDIN from the process point of view
OutputStream stdin = process.getOutputStream(); // write to this
So what you have should be correct.
My driver (apply your own best practices with try-with-resources statements)
public class ProcessWriter {
public static void main(String[] args) throws Exception {
ProcessBuilder builder = new ProcessBuilder("java", "Test");
builder.directory(new File("C:\\Users\\sotirios.delimanolis\\Downloads"));
Process process = builder.start();
OutputStream stdin = process.getOutputStream(); // <- Eh?
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write("Sup buddy");
writer.flush();
writer.close();
Scanner scanner = new Scanner(stdout);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
}
My application
public class Test {
public static void main(String[] args) throws Exception {
Scanner console = new Scanner(System.in);
System.out.println("heello World");
while(console.hasNextLine()) {
System.out.println(console.nextLine());
}
}
}
Running the driver prints
heello World
Sup buddy
For some reason I need the close(). The flush() alone won't do it.
Edit It also works if instead of the close() you provide a \n.
So with
writer.write("Sup buddy");
writer.write("\n");
writer.write("this is more\n");
writer.flush();
the driver prints
heello World
Sup buddy
this is more
This is an example which maybe can helps someone
import java.io.IOException;
import java.io.File;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
String[] commands = {"C:/windows/system32/cmd.exe"};
ProcessBuilder builder = new ProcessBuilder(commands);
builder.directory(new File("C:/windows/system32"));
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
InputStream stderr = process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
BufferedReader error = new BufferedReader(new InputStreamReader(stderr));
new Thread(() -> {
String read;
try {
while ((read = reader.readLine()) != null) {
System.out.println(read);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
String read;
try {
while ((read = error.readLine()) != null) {
System.out.println(read);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
while (true) {
try {
Scanner scanner = new Scanner(System.in);
writer.write(scanner.nextLine());
writer.newLine();
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}