繁体   English   中英

有没有办法知道用户是否使用readline()方法按下了ENTER键? -Java

[英]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键时,它将行尾序列添加到行缓冲区,然后发送行。

详细信息将取决于控制台程序以及用户对其的配置方式。 但是,事实仍然存在,直到用户键入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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM