2012-11-14 150 views
3

我在這裏有兩個代碼塊。一臺掃描儀正確等待用戶輸入,另一臺掃描儀正好通過它並呼叫nextInt(),該返回NoSuchElementException。這裏是工作的塊:Java掃描器不等待輸入

public void startGame() { 
    out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player."); 
    Scanner scan = new Scanner(System.in); 
    p = scan.nextInt(); 

    if (p == 1) 
     p1 = new DumbPlayer("ONE"); 
    if (p == 2) 
     p1 = new SmartPlayer("ONE"); 
    else 
     p1 = new HumanPlayer("ONE"); 

    out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player."); 
    p = scan.nextInt(); 

    if (p == 1) 
     p2 = new DumbPlayer("TWO"); 
    if (p == 2) 
     p2 = new SmartPlayer("TWO"); 
    else 
     p2 = new HumanPlayer("TWO"); 

    scan.close(); 

這裏是不塊:

public int findBestMove(Set<Integer> moves, Board b) { 

    Set<Integer> set = new HashSet<Integer>(); 

    out.println("Player " +name+ ", select a column from 1-7: "); 
    Scanner scan = new Scanner(System.in); <--here it should wait for input, but does not! 
    int move = scan.nextInt(); <-- NoSuchElementException 
    scan.close(); 

    for (int x = 1; x <= 7; x++) { 
     set.add(move); 
     move += 7; 
    } 
    ....etc 

這兩者都是獨立的類,並且在另一個類是從main方法調用。基本上main()調用startGame(),它依次調用一些Player類的findBestMove()方法...這是非工作代碼所在的地方。在計劃中是否有時候不適合採取投入?我的印象是,任何時候我想要用戶輸入,我都可以使用這種方法。謝謝!

+0

我在'findBestMove'中看到你做了一個'scan.close()',它也會關閉源碼流 - 你是否在'startGame()'中執行同樣的操作,在'etc'之後的某個地方執行? –

+1

在這個問題中討論的類似問題,不知道它是否應該關閉爲一個重複:http:// stackoverflow。com/questions/7056749/scanner-issue-when-using-nextline-after-nextint –

+0

@Dennis我在發帖之前看了一眼,我不認爲我的問題是相關的,但可能是錯誤的。 – Houdini

回答

3

根據java.util.Scanner javadocScanner.close()關閉相關流,如果此流實現Closeable接口。 java.lang.System.in是一個InputStream,它實現了Closeable接口。因此,在與System.in關聯的Scanner上調用Scanner.close()之後,System.in流將被關閉並且不再可用。

以下SSCCE適合我。我從與實際問題無關的問題中刪除了一些代碼。請注意,採用這種方法時,Eclipse會提供警告"Resource leak: 'scan' is never closed",所以更好的解決方案是僅使用一個Scanner實例。

package com.example; 

import java.util.Scanner; 
import java.util.Set; 
import static java.lang.System.out; 

public class ScannerTest { 
    int p = 0; 
    String name = "Test"; 

    public void startGame() { 
     out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player."); 
     Scanner scan = new Scanner(System.in); 
     p = scan.nextInt(); 

     out.println("Result1: " + p); 

     out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player."); 
     p = scan.nextInt(); 

     out.println("Result2: " + p); 

     // scan.close(); // Do not close the Scanner to leave System.in open 
    } 

    public int findBestMove(Set<Integer> moves, Object /*Board*/ b) { 
     out.println("Player " +name+ ", select a column from 1-7: "); 
     Scanner scan = new Scanner(System.in); 
     int move = scan.nextInt(); 
     // scan.close(); // Do not close the Scanner to leave System.in open 

     out.println("Move: " + move); 

     return 0; 
    } 

    public void run() { 
     startGame(); 
     findBestMove(null, null); 
    } 

    public static void main(String[] args) { 
     ScannerTest st = new ScannerTest(); 
     st.run(); 
    } 
} 
+0

非常感謝,別人也提到過,但是他們並沒有說'關閉()'已經在工作的班級了!這對我來說太奇怪了,當我宣佈新的掃描儀時,我不打開輸入流嗎?哦,現在工作,謝謝! – Houdini

+0

您可能知道這一點,但對於其他人也許可以閱讀,您可以執行'import static java.lang.System。*',這也只允許使用'out.println()'。 – Houdini

+0

謝謝:)我已經更新了示例代碼。無論如何,在使用靜態導入時,請務必查看[靜態導入](http://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html)文檔。通常我會避免通配符導入。我不確定是否寧願靜態導入'System.out'而不是明確指出'System.out',特別是因爲無論如何都隱式地導入了java.lang。*'。另見http://stackoverflow.com/questions/2504078/java-out-println-how-is-this-possible,特別是來自'Stephen C'的答案。 –

6

nextInt()不會在流中丟棄\n,所以下一次調用什麼也找不到。你必須與Scanner.skip("\n")Scanner.nextLine()

編輯手動跳過它搞清楚的是「跳過readInt()」指的是代碼拋出異常後。和@Andreas的幫助,這是一個替代解決方案。在java6中添加了一個新類Console,用於爲stdin提供更好的接口。它會返回一個不關心你關閉它多少的Reader。所以,下面的代碼片段工作得很好:

Scanner fi = new Scanner(System.console().reader()); 
    System.out.println(fi.nextInt()); 
    fi.close(); 

    fi = new Scanner(System.console().reader()); 
    System.out.println(fi.nextInt()); 
    fi.close(); 
+0

@Houdini:給nextInt()撥打電話之前 –

+0

爲什麼我必須在第二種情況下做,而不是第一種? – Houdini

+0

我試過了,但它或者說沒有找到任何行,或者在''\ n「'它說'在java.util.Scanner.skip(未知源)''的情況下。 – Houdini

0

嘗試使用的scan.reset();代替scan.close()。 Denis Tulskiy說,scan.close()會拋出NoSuchElementException。

+0

在'scan.close()'之前拋出異常。 – Houdini

+0

當然可以。我會添加細節。通過說scan.close()我的意思是使用它。事實上,當它掃描下一個發現掃描器已關閉的項目時,會拋出此錯誤。這就是我通過調試發現的。 – chAmi

+0

即使我將掃描儀打開,我也會得到相同的結果。 – Houdini

0

我剛剛花了大約15分鐘解決這個問題,我的問題是不同於以上所有。

該代碼是好的,但我使用Sublime Text並在終端模擬器中運行它,在窗口中的sublime文本中。這阻止了掃描器實際上允許我嘗試輸入內容。

我用cmd運行應用程序,它工作正常。我希望這可以幫助別人。