-->

如何管的InputStream的ProcessBuilder(How to pipe InputSt

2019-06-25 20:39发布

请向下移动到第二个更新。 我不想改变这个问题之前的环境。

我使用的是从一个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>";

我如何管contentSTDIN的过程中?

UPDATE ---

继安杰伊·多伊尔的答案:

我用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

月2日更新--------

当前码块是这样:

    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.

这样做还有什么我需要做,以保持管道的开启?

Answer 1:

从删除空白" - " -正常的空格被shell解释删除,但在这里ProcessBuilder ,它解释为(文字)的文件名开头,以一个空格结束。

(其实看过程的输出彼得建议可能早就告诉过你了...)



Answer 2:

异常在线程“主要”产生java.io.IOException:管道已结束

这意味着你已经开始的进程已经死亡。 我建议你阅读输出明白。 例如,它没有给你一个错误。



Answer 3:

是否有您使用DataInputStream类读取一个简单的文本文件中的原因是什么? 从Java文档

数据输入流允许应用程序的基本输入流中与机器无关的方式读取基本Java数据类型

这有可能是您正在阅读的文件的方式导致EOF被发送到OutputStream中造成管道来结束它得到您的字符串之前。

您的要求似乎是读取文件简单地将它传递给wkhtmltoimage过程之前追加到它。

你还缺少一份声明中关闭的OutputStream的过程。 这将导致进程等待(挂起),直到它从输入流中,这将是永远不会得到一个EOF。

我会用一个BufferedReader代替,并直接写入它的OutputStream的建议附加额外的字符串之前。 然后调用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();
}


Answer 4:

创建后Process的对象,你可以调用getOutputStream()以获得发送其内容进程的标准输入流的保持。

一旦你有这样抱着你可以使用Java的标准IO写什么字节到你想要的(包括作家包裹它,加入缓冲等)此流 - 并为你写他们,他们会被读只要他们冲洗处理。



Answer 5:

下面的代码工作,以及:

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


文章来源: How to pipe InputStream to ProcessBuilder