[英]Ignore earlier input when reading from console
我想 output 向控制台提出一個問題,然后得到問題后的下一行輸入是 output。
例如,我的程序可能正在休眠或進行一些耗時的計算,當用戶等待時,他們可能決定在控制台中輸入一些注釋(可能沒有按回車鍵,或者可能超過幾行)。 一旦睡眠完成,程序就會問用戶一個問題,“你叫什么名字?” 然后它應該等待包含用戶名的下一行輸入,並忽略用戶在睡眠進行時所做的任何隨機注釋。
這是一些嘗試這樣做的代碼:
public static void main(String[] args) throws InterruptedException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
System.out.println("What is your name?");
// while (scanner.hasNext()) {
// scanner.nextLine();
// }
String name = scanner.nextLine();
System.out.println("Hi, " + name);
}
當我在睡眠期間鍵入幾行時,其行為如下:
gpeo
hpotWhat is your name?
Hi, gpeo
問題是掃描器將從它讀取的最后一個輸入繼續讀取下一個輸入,而不是從最后一個System.out.println()
(這是有道理的)。 被注釋掉的代碼試圖通過首先閱讀所有先前的輸入來糾正該問題,然后再等待一行分配給name
。 但是, scanner.hasNext()
並沒有像我希望的那樣工作,因為當沒有下一個令牌時,它不會簡單地返回 false 而是等待另一個令牌(所以我不知道為什么它會費心返回 boolean 根本) .
令我困惑的另一件事是,在睡眠期間,如果您在一行上鍵入內容,該單行實際上會被忽略:
brbr irgjojWhat is your name?
A
Hi, A
我以為是 output Hi, brbr irgjojA
,所以這讓我覺得我可能誤解了控制台輸入和Scanner
的工作原理。
編輯:最后一個示例來自 IntelliJ 中的運行。 當我從 Bash 命令行運行時,我得到了Hi, brbr irgjojA
。 第一個示例的 output 並沒有改變。
另外,有人問我這個問題是否與this相同,顯然我必須解釋為什么它不在這里,否則它會出現在問題上。 該帖子(以及其他類似帖子)中的問題是他/她將scanner.nextLine()
與scanner.nextInt()
以及不讀取整行或行尾的類似方法混合在一起。 我只使用nextLine()
來讀取輸入,我的問題完全不同。
根據另一個問題的答案,我設法丟棄了第一行隨機筆記。 這是新代碼:
public static void main(String[] args) throws InterruptedException, IOException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
System.out.println("What is your name?");
while (System.in.available() > 0) {
scanner.nextLine();
}
String name = scanner.nextLine();
System.out.println("Hi, " + name);
}
以下是 IntelliJ 中的一些測試運行:
grgWhat is your name?
A
Hi, A
ghr
rhWhat is your name?
A
Hi, A
rghr
hrh
htWhat is your name?
Hi, hrh
uirh
iw
hjrt
sfWhat is your name?
Hi, iw
以下是 Bash 中的類似測試:
htrWhat is your name?
A
Hi, htrA
rgj
hrWhat is your name?
A
Hi, hrA
rjkh
ry
jWhat is your name?
Hi, ry
ryi
rj
rd
jrWhat is your name?
Hi, rj
如您所見,由於某種原因,while 循環內的行似乎從未多次執行。 我嘗試在循環內添加睡眠或使用其他InputStream
方法,如skip()
和readAllBytes()
,但這些似乎根本沒有幫助。
我認為對於 Bash 的問題的不完整行可能無能為力,但我確信必須有一種方法可以丟棄所有已完成的行(而不僅僅是第一行)。 該解決方案不必使用Scanner
,它應該按預期運行。
Scanner
使用緩沖區。 它的默認大小是 1024 個字符。 因此,通過第一個nextLine()
調用,它將多達 1024 個可用字符讀入緩沖區。 這是必要的,因為在填充緩沖區並在緩沖區中搜索換行符之前, Scanner
甚至不知道有多少字符屬於下一行。
因此,如果掛起的字符少於緩沖區大小,則循環將只迭代一次。 但即使有更多字符和更多循環迭代,生成的 state 也可能在緩沖區中有一些待處理的行。
只要Scanner
的緩沖區在其初始空 state 中,您就可以直接刷新源 stream,而不是使用掃描儀:
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
while(System.in.available() > 0) {
System.in.read(new byte[System.in.available()]);
}
System.out.println("What is your name?");
String name = scanner.nextLine();
System.out.println("Hi, " + name);
請注意,使用System.in.skip(System.in.available());
是很自然的。 而不是read
,但是在嘗試它時,我遇到了一個錯誤,即從控制台讀取時,底層 stream 在skip
后沒有更新available()
計數。
請注意,如果Scanner
不在其初始 state 但已經有一些緩沖內容,則無法刷新緩沖區,因為它的 API 旨在不區分緩沖和尚未緩沖,因此任何嘗試匹配所有內容將導致再次從源讀取(並阻塞)。 擺脫緩沖內容的最簡單解決方案是scanner = new Scanner(System.in);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.