2012-06-28 2 views
8

Пожалуйста, перейдите к второму обновлению. Я не хотел менять предыдущий контекст этого вопроса.Как подключить InputStream к ProcessBuilder

Я использую wkhtmltoimage из приложения Java.

Стандартный способ использования - 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>"; 

Как я труба content к STDIN процесса?

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

Doing так выдает ошибку, говоря:

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

Если вы не двигаться pb.start в конце программы? (после bw.write (content). Просто догадка, основанная на «как мы пишем процесс после того, как это началось!» – Sap

+0

@Grrrrr. Думаю, нам нужно будет начать процесс, чтобы получить его выходной поток. –

+3

Вы записываете данные в выходной поток, это означает, что «вы записываете данные в процесс!». Если вы хотите получить результат процесса, тогда вы должны сделать process.getInputStream, а затем прочитать его. – Sap

ответ

3

Удалить пробелы из " - " - нормальный пробелы удаляются синтаксическим анализатором оболочки, но здесь, в ProcessBuilder, оно интерпретируется как (литерал) имя файла, начинающееся и заканчивающееся пробелом.

(На самом деле, глядя на выходе процесса как Питер предложил бы, наверное, так сказал вам ...)

3

После создания объекта Process вы можете позвонить getOutputStream(), чтобы получить поток, который отправляет его содержимое в стандартный ввод процесса.

Как только вы это удержите, вы можете использовать стандартный IO Java для записи любых байтов в этот поток, который вы хотите (в том числе обернуть его в 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

Вполне возможно, что, как вы читаете файл вызывает EOF для отправки в OutputStream вызывая трубу до конца, прежде чем он попадает в строку.

Ваши требования, похоже, состоят в том, чтобы прочитать файл, просто добавив его, прежде чем передавать его в процесс 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; 
    } 
} 
Смежные вопросы