2010-11-23 5 views
2

Есть ли элегантный способ запускать событие, когда символы доступны от System.in? Я бы хотел избежать опроса InputStream.available().Как асинхронно читать stdin?

+0

Вы должны отметить, что System.in является буфером строки, поэтому вы не можете читать одно нажатие клавиши одновременно. Если вам требуется приложение для интерфейса, у вас должен быть графический интерфейс. – 2010-11-23 22:37:22

ответ

3

Вам нужно будет создать отдельный поток, который блокирует чтение до тех пор, пока что-то не будет доступно.

Если вы не хотите на самом деле есть вход, вам придется обернуть его внутренним буфером, прочитать в буфер, крикнуть, а когда его попросят ввести, верните данные из буфера.

Вы могли бы решить, как это:

InputStream stdin = System.in; 

// Create a wrapper (with it's own dedicated read-thread) 
MyListenableInputStream listenableInputStream = 
     new MyListenableInputStream(stdin); 

// Update System.in with something more useful. 
System.setIn(listenableInputStream); 
+0

Мощный ответ, спасибо. – 2011-04-30 04:29:56

2

Несомненно ... запустите поток, который блокируется на входе, а затем вызывает метод события, когда он что-то получает.

0
new Thread(){ 

    public void run() { 
     while(System.in.get()){ 
    } 

}.start(); 
0

Очень вообще говоря:

Если у вас уже есть реактор работает событие, создать поток и он блокирует на read(). Когда есть данные, попросите эту нить зарегистрировать событие для обработки реактора. Если вы не можете этого сделать, большинство реакторов событий предоставляют метод InvokeLater или CallLater, чтобы вы могли запускать некоторый код в потоке обработки событий.

После уведомления или планирования вызова функции вернитесь к блокировке на read().

0

Если вы хотите что-то элегантное, вы можете легко реализовать ObservableInputStream, который принимает Listener, который получает предупреждение о доступности данных, но вам придется реализовать его с помощью внутреннего потока, который периодически проверяет данные и вызывает слушателя в случае.

Подумайте о том, что потоки не должны использоваться как объекты, которые отправляют небольшие пакеты, но непрерывный поток байтов, поэтому этот подход будет работать, только если данные, переданные входному потоку, не будут эффективно поступает слишком часто (в противном случае он будет продолжать звонить слушателю ad libitum). Кроме того, вам нужно будет заботиться о согласованности, если данные поступят, когда что-то уже доступно, а слушатель предупреждается, тогда что-то может принимать все байты (которые вы должны разместить во временном буфере), но если есть еще данные, которые только что прибыли, решают, как обращаться (дайте его вместе с буфером, поместите в буфер и снова вызовите прослушиватель и т. д.)