2012-06-28 11 views
8

2番目の更新に移動してください。私はこの質問の前の文脈を変えたくありませんでした。InputStreamをProcessBuilderにパイプする方法

私はJavaアプリケーションからwkhtmltoimageを使用しています。

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

彼らのドキュメントによると、入力URLの代わりに-と書くと、入力は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>"; 

どのようにプロセスのSTDINにIパイプcontentしていますか?

私が使用したプロセスのgetOutputStream():アンジェイ・ドイルによって解答後

UPDATE ---

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 

第二UPDATE --------

現在のコードブロックのようなである:上記のコードを実行する

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

(ピーターが示唆されているように、実際のプロセスの出力を見ては、おそらく...ので、あなたに言っただろうか)? (bw.write(content)の後;「開始した後にプロセスにどのように書き込むのですか」に基づいてちょうど勘弁してください) – Sap

+0

@Grrrrよく、私たちは出力ストリームを取得するためにプロセスを開始する必要があると思います。 –

+3

あなたは出力ストリームにデータを書き込んでいます。これは「あなたはプロセスにデータを書き込んでいます!」と解釈します。プロセスの出力を取得するにはprocess.getInputStreamを実行してからそれを読み取る必要があります – Sap

答えて

3

" - "から空白を削除する - ノーマル空白はシェルパーサによって削除されますが、ここではProcessBuilderでは、空白で始まり、空白で終わる(リテラル)ファイル名として解釈されます。

あなたは、プログラムの最後にpb.start動くべきではありません

3

Processオブジェクトを作成した後、内容をプロセスの標準入力に送信するストリームを取得するために、getOutputStream()を呼び出すことができます。

これを保持すると、Javaの標準IOを使用して、このストリームに任意のバイトを書き込むことができます(Writerでラップしたり、バッファリングを追加するなど)。彼らがフラッシュされるとすぐにプロセスによって読み込まれます。

+0

私は 'getOutputStream'を使用して、バッファからプロセスに書き込みます。私はそれを正しくしていますか?私は質問を更新しました。 –

5

DataInputStreamを使用して単純なテキストファイルを読み取る理由はありますか? Javaドキュメント

A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way

から、それはあなたがファイルを読んでいる方法は、それはあなたの文字列に到達する前にパイプを終了させるOutputStreamに送信する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(); 
} 
+0

このソリューションは私の場合、投稿していただきありがとうございました!!! –

6

Exception in thread "main" java.io.IOException: The pipe has been ended

これは、あなたが開始されたプロセスが死亡したことを意味します。私はなぜ出力を読むことをお勧めします。例えばそれはあなたにエラーを与えましたか?

+0

プロセスのエラーストリームは同じことを言った - "パイプが終了しました"。 –

+0

私は 'waitFor'コマンドも追加しました:' process.waitFor(); ' –

+0

コマンドラインから実行するとこのようなエラーが発生するプログラムは見たことがありません。 –

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; 
    } 
} 
関連する問題