[英]Is there a way to know if a user pressed the key ENTER using readline() method? - Java
我想识别用户是否使用BufferedReader的readline方法发送了文本。 当用户未发送任何内容时,线程保持休眠状态。 有没有办法做到这一点? 我已经尝试了很长时间,但是还没有成功。.我想我必须要识别是否按了ENTER键。但是我不知道该怎么做。。我程序的界面是控制台。
问题是:我有一个客户端服务器程序。 客户端输入消息时,该消息将在另一个用户/客户端的屏幕上提示。 但是,如果用户在10秒内未发送消息,则希望消息出现在屏幕上。因此,我有一个Thread.sleep(1000)。 问题是我不知道何时唤醒线程。
while((mensagem == null) || (!mensagem.trim().equals(""))) {
Thread.sleep(10000);
sendToAll(output, "[Your turn] ", "");
mensagem = input.readLine();
}
最后一行也是不正确的,因为我不想强迫用户键入,因此我强制这样做,因为我停止在input.readLine()上了。
解决方案:我使用setSoTimeout(10000)方法解决了该问题。这是代码:
public Server(Socket socket) throws SocketException{
this.connection = socket;
this.connection.setSoTimeout(10000);
}
public void run(){
[...]
while((msg != null) && !(msg.trim().equals(""))){
try{
msg = input.readLine();
sendToAll(output, ": ", msg);
} catch (SocketTimeoutException e) {
sendToAll(output, "Time out ", "");
}
}
谢谢大家的想法! :)
您可以像这样阅读整行内容:
String in;
while ((in = br.readLine()) != null) {
// If this is triggered, in contains a whole line and if the input came from console that means enter was pressed
}
编辑:回应您的编辑:
input.readLine()
是一种阻塞方法。 它将继续尝试读取整行,直到收到一行,引发异常或到达EOF。 您的问题是您想要10秒钟的超时时间。 如果我错了纠正我。
这样做的方法是创建一个计时器或不受调用阻塞的线程来中断您的.readLine()调用。 您应该已经在其自己的线程中拥有所有的I / O,因此需要从另一个线程(主线程或使用计时器)创建一个定时事件,该事件将中断被阻塞的线程。 使用Timer的示例,在循环之前添加以下内容:
java.util.Timer t = new java.util.Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
IOHandlerClass.this.interrupt();
}
}, 10000);
用此代码放入的类的名称替换IOHandlerClass(您没有发布代码,所以我不知道名称)。
现在,除非您停止计时器,否则这将导致在10秒后引发InterruptException。 因此,用try-catch包围代码以捕获该异常,如果抛出该异常,则显示错误消息。 如果您确实在10秒钟的超时时间内获得了有效的响应,请记住取消计时器。
您需要了解Java端和控制台端的情况。
在Java方面, readLine()
调用只是尝试读取字符,直到看到有效的“行尾”序列(即输入流的末尾)为止。 这是一个阻塞调用,无法在您使用的API中指定超时。
在控制台方面,控制台正在监视键盘事件并将其累积在行缓冲区中:
详细信息将取决于控制台程序以及用户对其的配置方式。 但是,事实仍然存在,直到用户键入ENTER为止,什么都不会发送到将控制台连接到Java应用程序的“管道”。 简而言之,Java应用程序什么也看不到。
这意味着Java应用程序无法判断用户是否正在键入。
那么Java应用程序可以做什么?
几秒钟/分钟后,您可以使用Timer将中断发送到被阻塞的Java线程(执行readLine()
调用的中断)。 这将导致readLine()
调用取消阻塞并抛出IOException。 但是,这种方法存在问题:
在潜在的竞争情况下,在readLine()
调用完成后计时器将触发,并且中断将转到应用程序本身。 根据应用程序对中断的处理方式,这可能会导致问题。 您应该能够使用readLine
调用返回时主线程设置的正确同步标志来避免这种情况。
尚不完全清楚,但是有迹象表明,如果在管道上遇到中断,则基础通道会自动关闭。 这意味着您无法再要求用户提供更多输入。
第二种方法可能是使用NIO通道选择器替换BufferedReader
/ readLine()
代码。 除其他外, Selector
器使您可以等待超时以使通道具有可读数据。 然后,您需要在此之上实现缓冲和读取行。
如果您想知道用户是否在控制台上键入内容,则需要将控制台置于非行编辑模式。 在纯Java中无法做到这一点,但是有第三方库可以做到这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.