8

2回目の更新に移動してください。この質問の以前のコンテキストを変更したくありませんでした。

Java アプリから wkhtmltoimage を使用しています。

それを使用する標準的な方法は -path-to-exe http://url.com/ image.pngです。

彼らのドキュメントによると-、入力 URL の代わりに a を記述すると、入力は 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ですか?

アップデート - -

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

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.

パイプを開いたままにするには、他に何をする必要がありますか?

4

5 に答える 5

7

スレッド「メイン」の例外 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

空白を削除します" - "-- 通常の空白はシェル パーサーによって削除されますが、ここでは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 に答える