请转到第二次更新。我不想改变此问题的先前背景。
我正在使用Java应用程序中的wkhtmltoimage。
使用它的标准方法是 - path-to-exe http://url.com/ image.png
。
根据他们的文档,如果我们写一个-
而不是输入网址,输入会转移到STDIN。
我正在使用ProcessBuilder
-
ProcessBuilder pb = new ProcessBuilder(exe_path, " - ", image_save_path);
Process process = pb.start();
现在我无法弄清楚如何将输入流传输到此进程。
我有一个模板文件读入DataInputStream
,我在最后附加一个字符串:
DataInputStream dis = new DataInputStream (new FileInputStream (currentDirectory+"\\bin\\template.txt"));
byte[] datainBytes = new byte[dis.available()];
dis.readFully(datainBytes);
dis.close();
String content = new String(datainBytes, 0, datainBytes.length);
content+=" <body><div id='chartContainer'><small>Loading chart...</small></div></body></html>";
如何将content
传送到流程的STDIN
?
UPDATE ---
按照Andrzej Doyle的回答:
我使用过程的getOutputStream()
:
ProcessBuilder pb = new ProcessBuilder(full_path, " - ", image_save_path);
pb.redirectErrorStream(true);
Process process = pb.start();
System.out.println("reading");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
bw.write(content);
这样做会出错:
Exception in thread "main" java.io.IOException: The pipe has been ended
第二次更新--------
当前代码块如下:
try {
ProcessBuilder pb = new ProcessBuilder(full_path, "--crop-w", width, "--crop-h", height, " - ", image_save_path);
System.out.print(full_path+ "--crop-w"+ width+ "--crop-h"+ height+" "+ currentDirectory+"temp.html "+ image_save_path + " ");
pb.redirectErrorStream(true);
Process process = pb.start();
process.waitFor();
OutputStream stdin = process.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
// content is the string that I want to write to the process.
writer.write(content);
writer.newLine();
writer.flush();
writer.close();
} catch (Exception e) {
System.out.println("Exception: " + e);
e.printStackTrace();
}
运行上面的代码会给我一个IOException: The pipe is being closed.
我还需要做些什么来保持管道畅通?
答案 0 :(得分:7)
线程“main”中的异常java.io.IOException:管道已结束
这意味着你已经开始的过程已经死亡。我建议你阅读输出,看看为什么。例如它给你一个错误。
答案 1 :(得分:5)
您是否有理由使用DataInputStream来读取简单的文本文件?来自Java文档
数据输入流允许应用程序读取原始Java数据类型 来自与机器无关的基础输入流
您读取文件的方式可能会导致EOF被发送到输出流,导致管道在到达您的字符串之前结束。
您的要求似乎是在将文件传递给wkhtmltoimage进程之前简单地将其附加到文件中。
您还缺少关闭流程输出流的语句。这将导致进程等待(挂起),直到它从输入流中获得EOF,这将永远不会。
我建议使用BufferedReader,并在附加其他字符串之前将其直接写入输出流。然后调用close()关闭流。
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();
}
答案 2 :(得分:3)
创建Process
对象后,您可以调用getOutputStream()
以获取将其内容发送到进程标准输入的流。
一旦掌握了这一点,就可以使用Java的标准IO将所需的字节写入所需的流(包括将其包装在Writer中,添加缓冲等) - 当你编写它们时,它们将是一旦他们被冲洗,他们会立即阅读。
答案 3 :(得分:3)
从" - "
中删除空格 - shell解析器删除了正常的空格,但在ProcessBuilder
中,它被解释为(文字)文件名开头和结尾的空格。 / p>
(实际上看彼得建议的过程的输出可能已经告诉过你了......)
答案 4 :(得分:1)
以下代码也适用:
import java.io.*;
import java.util.*;
public class ProcessTest {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("/home/me/stdinecho");
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process proc = pb.start();
// Input file
DataInputStream din = new DataInputStream((new FileInputStream("/home/me/stdinecho.cp")));
byte[] dinBytes = new byte[din.available()];
din.readFully(dinBytes);
din.close();
String content = new String(dinBytes, 0, dinBytes.length);
content = "header\n" + content + "\nfooter";
BufferedInputStream procStdout = new BufferedInputStream(proc.getInputStream());
OutputStream stdin = proc.getOutputStream();
stdin.write(content.getBytes());
stdin.flush();
}
}
这里stdinecho.cpp是输出在其提示符下输入的行的程序:
#include <iostream>
#include <fstream>
#include <cstdio>
using namespace std;
int main()
{
string strOutput;
string str;
while(getline(cin, str)) {
cout << str << endl;
}
}