Как автоматизировать сценарий командной строки с помощью Java ProcessBuilder - PullRequest
0 голосов
/ 25 октября 2018

Я новичок в Java и пытаюсь автоматизировать командную строку, используя Java.Я пытался найти решение здесь, но не смог его найти.

Я создал простой сценарий тестовой оболочки, как показано ниже для тестирования моей программы:


#!/bin/bash
echo "What is your name?";
read name;
echo "Hello, $name"
echo "What is your contact number?";
read num;
echo "Saved contact number $num for $name"

Ниже приведен код Java:

import java.io.*;
import java.util.*;

public class CmdLineMain {
    public static void main(String args[]) throws InterruptedException, IOException {
        List<String> command = new ArrayList<String>();
        command.add("./test.sh");

        ProcessBuilder builder = new ProcessBuilder(command);

        final Process process = builder.start();
        InputStream is = process.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line = "";
        BufferedWriter bw = null;

        while (process.isAlive()) {
            line = br.readLine();
            // since stream may be closed earlier, re-open it
            bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
            System.out.println(line);

            if (line != null) {
                switch (line) {
                case "What is your name?":
                    bw.write("John Doe");
                    bw.close();
                    break;
                case "What is your contact number?":
                    bw.write("123456789");
                    bw.close();
                    break;

                }
            }

        }

        System.out.println("Program terminated!");
    }
}

Проблема: Ошибка второго входа процесса:


    What is your name?
    Hello, John Doe
    What is your contact number?
    Exception in thread "main" java.io.IOException: Stream Closed
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:326)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        at java.io.FilterOutputStream.close(FilterOutputStream.java:158)
        at sun.nio.cs.StreamEncoder.implClose(StreamEncoder.java:320)
        at sun.nio.cs.StreamEncoder.close(StreamEncoder.java:149)
        at java.io.OutputStreamWriter.close(OutputStreamWriter.java:233)
        at java.io.BufferedWriter.close(BufferedWriter.java:266)
        at nkh.app.CmdLineMain.main(CmdLineMain.java:34)

1 Ответ

0 голосов
/ 25 октября 2018

Закрытие BufferedWriter закроет лежащие в его основе потоки, в том числе процесс OutputStream, который вы получаете через process.getOutputStream().Таким образом, как только он будет закрыт в одном цикле, в следующих циклах у вас будет BufferedWriter, оборачивающий закрытый поток.Вместо этого оберните выходной поток только один раз и используйте его повторно.

Пример:

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
// while the stream is open and there is something to read
// probably a better condition than `process.isAlive()`
while ((line = br.readLine()) != null) {
    switch (line) {
        case "What is your name?":
            bw.write("John Doe");
            bw.newLine();
            bw.flush();
            break;
        case "What is your contact number?":
            bw.write("123456789");
            bw.newLine();
            bw.flush();
            break;
    }
}

Причина, по которой исходный код умер на close(), а не на write(), которыйпредшествовал этому, когда ваш новый BufferedWriter упаковывал закрытый базовый поток, потому что BufferedOutputStream.write() может еще не записывать в базовый поток, так как он буферизован.Вызов flush() должен указать потоку на фактическую запись, и, как вы видите в трассировке стека, close() вызывает flush(), который в конечном итоге записывает буферизованные байты в базовый FileOutputStream, который затем осознает, что FileOutputStream уже закрыт.

...