Linux 读取前刷新/清除 System.in (stdin)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18273751/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Flush/Clear System.in (stdin) before reading
提问by Lukas Knuth
At work, we have 5 RFID readers attached to a PC running Linux. The readers are all recognized as keyboards and send their input (what they read form the Chip) as an key-input-event sequence. To be able to tell which reader send what sequence, I'm doing a raw-read over /dev/input/XX
and get their input this way.
在工作中,我们有 5 个 RFID 阅读器连接到运行 Linux 的 PC。阅读器都被识别为键盘,并将他们的输入(他们从芯片读取的内容)作为键输入事件序列发送。为了能够知道哪个读者发送了什么序列,我正在做一个原始阅读/dev/input/XX
并以这种方式获取他们的输入。
The problem with this is, that the send keyboard-events generated by the RFID readers are still "in" stdin and when I try to read from System.in
via Scanner
(input should be generated by a normal keyboard this time), I first get the "pending" input from the readers (which consists of 10 Hex-decimal digits and a newline (\n
)).
问题是,由 RFID 阅读器生成的发送键盘事件仍然“在”标准输入中,当我尝试从System.in
via读取时Scanner
(这次输入应该由普通键盘生成),我首先得到“pending " 来自阅读器的输入(由 10 个十六进制数字和一个换行符 ( \n
) 组成)。
Now, the question is: How can I flush all these "pending" input's from stdinand then read what I really want from the keyboard?
现在,问题是:如何从标准输入中刷新所有这些“待处理”输入,然后从键盘读取我真正想要的内容?
I tried:
我试过:
System.in.skip(System.in.available());
But seek is not allowed on stdin (skip
throws an IOException
).
但是在标准输入上不允许搜索(skip
抛出一个IOException
)。
for (int i = 0; i < System.in.available(); i++){
System.in.read();
}
But available()
doesn't estimate enough (still stuff in stdin afterwards).
但available()
估计不够(之后仍然在标准输入中)。
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()){
scanner.nextLine();
}
System.out.println("Clean!");
But hasNextLine()
never becomes false
(the print never executes).
但hasNextLine()
永远不会成为false
(打印永远不会执行)。
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null);
System.out.println("Clean!");
Same as above.
和上面一样。
Anyone with any more ideas?
有人有更多想法吗?
采纳答案by Lukas Knuth
Based on @Joni's advice, i put this together:
根据@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...
}
}
This discards the data that is already "pending" in stdin and waits until valid data is entered. Valid, in this context, meaning a decimal integer.
这会丢弃标准输入中已经“待处理”的数据,并等待输入有效数据。有效,在此上下文中,表示十进制整数。
回答by William Morrison
Devices usually send data using a well defined protocol which you can use to parse data segments.
设备通常使用定义明确的协议发送数据,您可以使用该协议解析数据段。
If I'm right, discard data that isn't properly formatted for the protocol. This allows you to filter out the data you aren't interested in.
如果我是对的,丢弃那些格式不适合协议的数据。这允许您过滤掉您不感兴趣的数据。
As I'm not familiar with the RFID scanner you're using I can't be of more help, but this is what I suggest.
由于我不熟悉您正在使用的 RFID 扫描仪,因此我无法提供更多帮助,但这就是我的建议。
回答by Joni
There is no built-in portable way to flush the data in an input stream. If you know that the pending data ends with \n
why don't you read until you find it?
没有内置的可移植方式来刷新输入流中的数据。如果您知道待处理的数据以以下方式结束,\n
为什么在找到它之前不阅读呢?
回答by Lukas Knuth
This worked for me
这对我有用
System.in.read(new byte[System.in.available()])
回答by Erwin Bolwidt
You could do this with multiple threads.
您可以使用多个线程执行此操作。
- Your real application reads from a PipedInputStream that is connected to a PipedOutputStream
- You need to have one thread reading from
System.in
continuously. As long as the real application is not interested in the data coming from System.in (indicated by a boolean flag), this thread discards everything that it reads. But when the real application sets the flag to indicate that it is interested in the data coming from System.in, then this thread sends all the data that it reads to the PipedOutputStream. - Your real application turns on the flag to indicate that it is interested in the data, and clears the flag when it is no longer interested in the data.
- 您的真实应用程序从连接到 PipedOutputStream 的 PipedInputStream 读取
- 您需要
System.in
连续读取一个线程。只要实际应用程序对来自 System.in 的数据(由布尔标志表示)不感兴趣,该线程就会丢弃它读取的所有内容。但是,当实际应用程序设置标志以表明它对来自 System.in 的数据感兴趣时,该线程会将它读取的所有数据发送到 PipedOutputStream。 - 您的实际应用程序打开该标志以表明它对数据感兴趣,并在它不再对数据感兴趣时清除该标志。
This way, the data from System.in
is always automatically flushed/clead
这样,来自的数据System.in
总是自动刷新/clead
回答by Manohar Reddy Poreddy
A related one.
一个相关的。
I read a double, then needed to read a string.
我读了一个双,然后需要读一个字符串。
Below worked correctly:
以下工作正常:
double d = scanner.nextDouble();
scanner.nextLine(); // consumes \n after the above number(int,double,etc.)
String s = scanner.nextLine();
回答by veganaiZe
The best practice (that I've found) when dealing with terminals(aka. the console) is to deal with i/o a line at a time. So the ideal thing to do is get the entire line of user input, as a string, and then parse it as you see fit. Anything else is not only implementation specific, but also prone to blocking.
处理终端(又名控制台)时的最佳实践(我发现)是一次处理 i/oa 线。因此,理想的做法是获取用户输入的整行,作为 string,然后按照您认为合适的方式对其进行解析。其他任何东西不仅是特定于实现的,而且容易阻塞。
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) {}
}
I include the while
& try/catch
blocks so that the prompt will loop infinitely on invalid input.
我包含while
&try/catch
块,以便提示将在无效输入上无限循环。