Я пытаюсь разрешить связь между одной программой (программа запуска, если хотите), и программами, которые запускаются через Processbuilder. Я работаю нормально, но вход, кажется, останавливается, когда он достигает метода readline() в helloworld (созданный процесс).
Ниже приведена helloworld.java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class helloworld {
public static void main (String[] args) {
System.out.println ("println(\"Hello World!\")");
System.out.println ("getInput()");
Scanner in = new Scanner(System.in);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String input = "";
try {
// wait until we have data to complete a readLine()
while (!br.ready()) {
Thread.sleep(200);
}
System.out.println("println(\"Attempting to resolve input\")");
input = br.readLine();
^ Здесь программа зависает ^
if(input != null){
System.out.println("println(\"This should appear\")");
}
System.out.println("println(\"input recieved " + input + "\")");
} catch (InterruptedException | IOException e) {
System.out.println("ConsoleInputReadTask() cancelled");
}
System.out.println("println(\"You said: " + input + "\")");
//System.out.println("println(\"You said: " + in. + "!\")");
in.close();
System.exit(0);
}
}
Это результат вывода (println) из другого процесса:
public void run() {
try {
//cfile = files[indexval].getAbsolutePath();
String[] commands =
{
"java", //Calling a java program
"-cp" , //Denoting class path
cfile.substring(0,cfile.lastIndexOf(File.separator) ), //File path
program}; //Class name
ProcessBuilder probuilder = new ProcessBuilder( commands );
//start the process
Process process = probuilder.start();
//Read out dir output
//probuilder.inheritIO(); //Can inherit all IO calls
InputStream is = process.getInputStream();
OutputStream os = process.getOutputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
BufferedReader br = new BufferedReader(isr);
String line;
/*System.out.printf("Output of running %s is:\n",
Arrays.toString(commands));*/
while ((line = br.readLine()) != null) {
myController.runCommand(line, "Please enter something!", bw);
//System.out.println(line);
}
br.close();
os.close();
} catch (IOException e){
e.printStackTrace();
}
System.out.println("programclosed");
}
И вот функция, которую он вызывает:
public synchronized void runCommand(String line, Object... arguments) throws IOException {
String[] tokens;
if(line.contains("(")){
tokens = line.split("\\(",2);
switch(tokens[0]){
case "println": //Println - format println(String strng)
tokens[1] = tokens[1].substring(1, tokens[1].length() - 2);
System.out.println(tokens[1]);
break;
case "getInput": //Get input - format getInput(String command, String message, BufferedWriter br)
Scanner reader = new Scanner(System.in);
System.out.println(arguments.length);
System.out.println(((String)arguments[0]));
BufferedWriter in = ((BufferedWriter)arguments[1]);
in.write(reader.nextLine());
System.out.println("sending input");
in.flush();
reader.close();
break;
default:
System.out.println("Invalid command recieved!");
}
} else
System.out.println("Invalid command recieved!");
}
Получаемый результат:
Привет мир!
2 Пожалуйста, введите что-нибудь!
Это тестовый ввод
отправка ввода
Попытка разрешить ввод
Как вы можете видеть, я успешно завершаю цикл while (! Br.ready()), и я останавливаюсь на br.readLine();
Я знаю, что inheritIO() существует, но для этого случая я использую BufferedOuput для отправки команд, которые затем разбираются и отправляются в оператор switch, который, в свою очередь, вызывает соответствующую функцию. Это связано с тем, что из диспетчера процессов можно запускать несколько процессов, думать о том, как весело при приходе нескольких вызовов System.in, и ничто не определяет, для какого процесса он нужен! Кроме того, это позволяет мне вызвать любой тип функции, даже те, которые не связаны с println или input.
Я считаю, что проблема здесь заключается в следующем:
BufferedReader.ready()
возвращает true
если есть доступные символы для чтения. Это не гарантирует, что между ними есть каретки. (docs)BufferedReader.readLine()
ищет возврат каретки для завершения строки. Если он не найден, он блокируется.BufferedWriter.write()
не записывает автоматически завершающий возврат каретки. Чтобы проверить, действительно ли это проблема, замените эту строку в runCommand()
:
in.write(reader.nextLine());
с:
in.write(reader.nextLine() + "\n");
ready().
Последующий . ВызовreadLine()
уже заблокирует, и в течение точно правильного промежутка времени, в отличие от этого цикла, который почти всегда будет сбрасываться.