8

请移至第二次更新。我不想更改此问题的先前上下文。

我正在使用来自 Java 应用程序的 wkhtmltoimage。

使用它的标准方式是 - path-to-exe http://url.com/ image.png

根据他们的文档,如果我们编写 a-而不是输入 URL,则输入将转移到 STDIN。

我正在使用ProcessBuilder-

ProcessBuilder pb = new ProcessBuilder(exe_path, " - ", image_save_path);

Process process = pb.start();

现在我无法弄清楚如何将输入流通过管道传输到这个进程。

我有一个模板文件读入 a 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>";

我如何管道contentSTDIN进程?

更新 - -

按照 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.

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

4

5 回答 5

7

线程“main”java.io.IOException 中的异常:管道已结束

这意味着您启动的进程已经终止。我建议您阅读输出以了解原因。例如,它给你一个错误。

于 2012-08-07T13:38:22.137 回答
6

您使用 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();
}
于 2012-08-06T09:04:42.423 回答
3

创建Process对象后,您可以调用getOutputStream()以获取将其内容发送到进程的标准输入的流。

一旦掌握了这一点,您就可以使用 Java 的标准 IO 将任何字节写入您想要的 this 流(包括将其包装在 Writer 中,添加缓冲等) - 当您编写它们时,它们将被读取冲洗后立即处理。

于 2012-06-28T09:51:56.537 回答
3

Remove the whitespace from " - "-- 正常的空格被 shell 解析器删除,但在 中ProcessBuilder,它被解释为以空格开头和结尾的(文字)文件名。

(实际上,按照彼得的建议查看流程的输出可能会告诉你......)

于 2012-08-10T11:38:55.297 回答
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;
    }
}
于 2012-08-10T09:50:41.070 回答