如何将InputStream传递给ProcessBuilder

时间:2012-06-28 09:34:33

标签: java stdin java-io wkhtmltopdf processbuilder

请转到第二次更新。我不想改变此问题的先前背景。

我正在使用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.

我还需要做些什么来保持管道畅通?

5 个答案:

答案 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;
    }
}