如何异步读取stdin?
当 System.in 中的字符可用时,是否有一种优雅的方式来触发事件?我想避免轮询 InputStream.available()
。
Is there an elegant way to fire an event when characters are available from System.in
? I'd like to avoid polling InputStream.available()
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您必须创建一个单独的线程来阻止读取,直到有可用的内容为止。
如果您不想真正耗尽输入,则必须用内部缓冲区将其包装起来,读入缓冲区,然后在要求输入时从缓冲区返回数据。
你可以这样解决:
You would have to create a separate thread that blocks in read until something is available.
If you don't want to actually eat up the input, you would have to wrap it with an internal buffer, read into the buffer, shout, and when asked for the input, give back data from the buffer.
You could solve it like this:
当然...启动一个阻塞输入的线程,然后在获取某些内容时调用您的事件方法。
Sure...start a thread that blocks on the input and then calls your event method when it gets something.
一般来说:
如果您已经运行了一个事件反应器,请创建一个线程并让它在
read()
上阻塞。当有可用数据时,让该线程将事件排入队列以供反应器处理。如果您无法执行此操作,大多数事件反应器都会提供InvokeLater
或CallLater
方法,供您在事件处理线程中运行一些代码。通知或安排函数调用后,返回到
read()
上阻塞。Very generally speaking:
If you already have an event reactor running, create a thread and have it block on
read()
. When there's data available, have that thread enqueue an event for the reactor to process. If you can't do this, most event reactors provide anInvokeLater
, orCallLater
method, for you to run some code in the event processing thread.After notifying or scheduling a function call, go back to blocking on
read()
.如果您想要一些优雅的东西,您可以轻松实现一个 ObservableInputStream ,它接受一个监听器,该监听器会收到有关数据可用性的警告,但您必须使用定期检查的内部线程来实现它获取数据并调用侦听器以防万一。
考虑一下这样一个事实:流不应该用作发送小数据包的对象,而是发送连续的字节流,这就是为什么这种方法只有在提供给输入流的数据实际上没有频繁到达的情况下才有效(否则它会继续随意调用监听器)。此外,您还必须关心一致性,如果数据在某些内容已经可用并且侦听器被警告时到达,那么某些内容可能会占用所有字节(您应该将其放置在临时缓冲区中),但是如果有更多数据刚刚到达,您应该决定如何处理(将其与缓冲区一起提供,放入缓冲区并再次调用侦听器等)
If you want something elegant you could easily implement an
ObservableInputStream
which accepts aListener
that gets warned about availability of data but you will have to implement it with an inner thread that periodically checks for data and call the listener in case.Think about the fact that streams aren't supposed to be used as object that send small packets but a continuous stream of bytes, that's why this approach would work only if the data that is given to the input stream doesn't effectively arrives too often (otherwise it would keep calling the listener ad libitum). In addition you will have to care about consistency, if data arrive when something is already available and the listener is warned then something can take all the bytes (which you should place in a temporary buffer) but if there's more data that just arrived you should decide how to handle (give it together with buffer, place in buffer and call listener again, etc)