Как заставить java OutputStreamWriter на самом деле записать один байт? - PullRequest
1 голос
/ 17 марта 2019

Я пытаюсь запустить простую эхо-программу из Java (используя ProcessBuilder), существует бесконечный цикл, в котором я получаю ввод от пользователя (используя Scanner). Затем я использую OutputStreamWriter, чтобы записать его в стандартный поток процесса, и я ожидаю увидеть ту же строку, возвращаемую обратно через стандартный вывод, но этого не произойдет, если я не закрою поток (что я не хочу) или я пишу длинная строка ven при вызове flush, если строка короткая (например, 1 символ), она не работает.

Как мы можем форсировать, даже для односимвольных (коротких) строк?

ProcessBuilder pb = new ProcessBuilder(cmd);
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
OutputStream stdin = p.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(stdin);
Scanner scanner = new Scanner(System.in);
String line;
while (true) {
    String input = scanner.nextLine();
    if (input.equals("q"))
        break;
    writer.write(input+"\n");
    writer.flush();
    // writer.close(); (uncommenting this makes it work once, then throw error)
    line = br.readLine();
    System.out.println(line);
}

Редактировать 3/18: Я попробовал инструменты Windows sysinternals для отслеживания системных вызовов записи, и, похоже, мои предположения верны, сброс не работает, если это не длинная строка (или если вы не закрыли поток).
Edit 3/19: Я нашел это: Блокирует ли fgets () стандартный вывод, предотвращая printf , что делает вещи еще более интересными.

Ответы [ 2 ]

1 голос
/ 17 марта 2019

Проблема во взаимодействии с a.exe.

a.exe использует fgets.Он останавливается, когда читается (n-1) символов, читается символ новой строки или достигается конец файла, в зависимости от того, что произойдет раньше.

Вы не переводите новую строку на a.exeТаким образом, fgets может дополняться только EOF, что происходит при закрытии потока.

Либо вы можете передать конец строки из Java, либо вы можете использовать другую функцию чтения на стороне C.

Чтобы вставить конец строки, вы можете использовать:

writer.write(System.lineSeparator());

См .: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm

0 голосов
/ 19 марта 2019

Вопрос [окончательно] решен благодаря этому вопросу:
Блокирует ли fgets () стандартный вывод, предотвращая печатьf
Так что проблема на самом деле не была ошибкой Java, это одна из особенностейокон, здесь я подключил потоки к stdin и stdout, и пока я не закрыл stdin, он не пишет в stdout.
Итак, решение: 1) сбросить стандартный вывод на стороне «a.exe».ИЛИ 2) просто не используйте оба потока.Например, на стороне «a.exe» вместо stdout пишите в файл, а на стороне java используйте этот файл.
(1) - лучший вариант, если у вас есть доступ к «a.exe», но это может быть внешняя программа, к которой у вас нет доступа.

...