【问题标题】:Flush/Clear System.in (stdin) before reading在读取之前刷新/清除 System.in (stdin)
【发布时间】:2013-08-18 21:15:38
【问题描述】:

在工作中,我们将 5 个 RFID 阅读器连接到运行 Linux 的 PC 上。阅读器都被识别为键盘,并将他们的输入(他们从芯片中读取的内容)作为键输入事件序列发送。为了能够分辨哪个阅读器发送什么序列,我正在对/dev/input/XX 进行原始阅读并以这种方式获取他们的输入。

问题在于,RFID 阅读器生成的发送键盘事件仍然在标准输入中,当我尝试通过 ScannerSystem.in 读取时(输入应该由普通键盘生成时间),我首先从读者那里得到“待定”输入(由 10 个十六进制数字和一个换行符 (\n) 组成)。

现在,问题是:如何从标准输入刷新所有这些“待处理”输入,然后从键盘读取我真正想要的内容?

我试过了:

System.in.skip(System.in.available());

但在标准输入上不允许搜索(skip 抛出 IOException)。

for (int i = 0; i < System.in.available(); i++){
  System.in.read();
}

但是available() 估计不够(之后仍然在标准输入中)。

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()){
  scanner.nextLine();
}
System.out.println("Clean!");

hasNextLine() 永远不会变成false(打印永远不会执行)。

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null);
System.out.println("Clean!");

同上。

谁有更多的想法?

【问题讨论】:

  • Scanner.hasNextLine() 如果没有输入可能会阻塞,所以我怀疑你的打印语句永远不会因为这个原因执行。不是解决方案,而是观察为什么至少有一种方法失败了。
  • (没有足够的代表发表评论)...这太棒了:这对我有用 System.in.read(new byte[System.in.available()]) 用户5466753**

标签: java linux stdin keyboard-events


【解决方案1】:

你可以试试:

System.in.skipNBytes(System.in.available());

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

处理终端(又名控制台)时的最佳做法(我发现)是处理 i/oa一次一行。因此,理想的做法是获取整行用户输入,作为字符串,然后按照您认为合适的方式对其进行解析。其他任何东西不仅是特定于实现的,而且容易阻塞。

Scanner sc = new Scanner(System.in);
String line = "";

while (true) {
    System.out.println("Enter something...");

    try {
        line = sc.nextLine();
        //Parse `line` string as you see fit here...
        break;
    } catch (Exception e) {}
}

我包含了 whiletry/catch 块,以便提示将在无效输入时无限循环。

【讨论】:

    【解决方案3】:

    一个相关的。

    我读了一个双精度数,然后需要读一个字符串。

    以下工作正常:

    double d = scanner.nextDouble();
    scanner.nextLine(); // consumes \n after the above number(int,double,etc.)
    String s = scanner.nextLine();
    

    【讨论】:

      【解决方案4】:

      您可以使用多个线程来执行此操作。

      1. 您的实际应用程序从连接到 PipedOutputStream 的 PipedInputStream 读取数据
      2. 您需要有一个线程连续读取System.in。只要真正的应用程序对来自 System.in 的数据(由布尔标志指示)不感兴趣,该线程就会丢弃它读取的所有内容。但是,当真正的应用程序设置标志以表明它对来自 System.in 的数据感兴趣时,该线程会将它读取的所有数据发送到 PipedOutputStream。
      3. 您的实际应用程序打开标志以表明它对数据感兴趣,并在不再对数据感兴趣时清除标志。

      这样,System.in 中的数据总是会自动刷新/清除

      【讨论】:

        【解决方案5】:

        这对我有用

        System.in.read(new byte[System.in.available()])
        

        【讨论】:

          【解决方案6】:

          根据 @Joni 的建议,我整理了以下内容:

          Scanner scanner = new Scanner(System.in);
          int choice = 0;
          while (scanner.hasNext()){
              if (scanner.hasNextInt()){
                  choice = scanner.nextInt();
                  break;
              } else {
                  scanner.next(); // Just discard this, not interested...
              }
          }
          

          这会丢弃标准输入中已经“待定”的数据,并等待输入有效数据。有效,在此上下文中,表示十进制整数。

          【讨论】:

            【解决方案7】:

            没有内置的可移植方式来刷新输入流中的数据。如果您知道待处理的数据以\n 结尾,为什么不阅读,直到找到它?

            【讨论】:

              【解决方案8】:

              设备通常使用定义明确的协议发送数据,您可以使用该协议来解析数据段。

              如果我是对的,请丢弃协议格式不正确的数据。这使您可以过滤掉您不感兴趣的数据。

              由于我不熟悉您使用的 RFID 扫描仪,因此我无法提供更多帮助,但这是我的建议。

              【讨论】:

              • 传入的数据可能是格式化的,我也对它感兴趣,但不是在那个时候。我怀疑数据仍在 stdio 中,因为我从未从 stdio 中获取它,而是从设备本身读取它...
              猜你喜欢
              • 1970-01-01
              • 2019-04-02
              • 2020-08-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-04-10
              相关资源
              最近更新 更多