Java Scanner.nextLine()不等待输入 [英] Java Scanner.nextLine() not waiting for input

查看:97
本文介绍了Java Scanner.nextLine()不等待输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我之前使用了几种方法来接受用户输入,并将其作为特定数据类型返回给调用它的方法。我在之前的项目中使用过这些方法或它们的变体。

I have several methods that I've used previously to accept user input and return it as a certain data type to the method that calls for it. I have used these methods, or variations of them, in previous projects.

我采用了我用于字符串的方法来选择给定的第一个字符并返回,以便我可以在菜单中使用它。每次启动应用程序时,都会出现主菜单并等待用户输入。收到此输入后,程序会一直循环直到停止。这是我捕获char的方法:

I've adopted the method that I used for string to select the first char given and return that, so that I can use this in a menu. Every time I start the application, the main menu appears and waits for user input. After receiving this input, the program loops continuously until stopped. Here is my method for capturing the char:

private char getUserChar(String prompt) {
    try {
        Scanner scan = new Scanner(System.in);
        System.out.print(prompt);
        String tempString = "";
        tempString = scan.nextLine();
        scan.close();
        char userChar = tempString.charAt(0);
        return userChar;
    } catch(Exception ex) {
        System.out.println(ex.getMessage());
    }
    return 0;
}

代码循环由try / catch块引起,如scan.nextLine( )永远不会等待下一个输入。没有它,例外通常与找不到新行有关。我尝试了似乎适合其他人的while(scan.hasNextLine());但是,一旦输入的时间到来,它就永远不会脱离循环。我也不相信我正在绊倒每个人似乎都遇到麻烦的nextInt()问题。我将在下面发布整个类的代码:

The code loops due to the try/catch block, as scan.nextLine() never waits for the next input. Without it, the exception is typically related to not finding a new line. I've tried the while(scan.hasNextLine()) that seems to work for other people; however, once the time for input arrives, it never breaks out of the loop. I also don't believe I'm tripping up on the nextInt() issue that everyone seems to have troubles with. I'll post the code for the entire class below:

import java.util.Scanner;
import controller.Controller;
public class TUI {
    private Controller controller;
    public TUI() {
        Controller controller = new Controller();
        this.controller = controller;
    }

    public void run() {
        boolean wantToQuit = false;
        char userInput = 0;
        System.out.println("Welcome to the Mart.");
        do{
            userInput = mainMenu();
            if(isUserInputValid(userInput))
                switch(userInput){
                    case 'a': addItem();
                    break;
                    case 'r': controller.removeItem();
                    break;
                    case 'i': controller.printInventory();
                    break;
                    case 'p': controller.customerPurchase();
                    break;
                    case 'w': controller.weeklyStock();
                    break;
                    case 'c': wantToQuit = true;
                    break;
                }
            else System.out.println("\nMainMenu");



        } while(!(wantToQuit));
        System.out.println("WolfMart is now closed.  Thank you and good-bye.");
    }




    private boolean isUserInputValid(char userInput) {
        char[] testSet = {'a', 'r', 'i', 'p', 'c', 'w'};
        for(char currentChar : testSet) {
            if(currentChar == userInput)
                return true;
        }
        return false;
    }

    private char mainMenu() {
        System.out.println();
        controller.printInventory();
        String mainMenuSelection = "What would you like to do: (a)dd item, (r)emove item, print (i)nventory, " +
            "(p)urchase by customer, (c)lose store?\r\n";

        char mainMenuInput = getUserChar(mainMenuSelection);
        return mainMenuInput;
    }

    private char getUserChar(String prompt) {
        try {
            Scanner scan = new Scanner(System.in);
            System.out.print(prompt);
            String tempString = "";
            tempString = scan.nextLine();
            scan.close();
            char userChar = tempString.charAt(0);
            return userChar;
        } catch(Exception ex) {
            System.out.println(ex.getMessage());
        }
        return 0;
    }


    private int getUserInt(String prompt) {
        Scanner scan = new Scanner(System.in);
        int userInt = -1;
        try {
            System.out.print(prompt);
            String input = scan.nextLine();
            userInt = Integer.parseInt(input);
        }
        catch(NumberFormatException nfe) {
            System.out.println("I did not recognize your command, please try again.");
        }
        scan.close();
        return userInt;
    }

    private String getUserString(String prompt) {
        Scanner scan = new Scanner(System.in);
        String userString = null;
        try{
            System.out.print(prompt);
            userString = scan.nextLine();
        } catch(Exception ex)
        {
            System.out.println("I did not recognize your command, please try again.");
        }
        scan.close();
        return userString;
    }

    private double getUserDouble(String prompt) {
        Scanner scan = new Scanner(System.in);
        double userDouble = -1.0;
        try {
            System.out.print(prompt);
            String input = scan.nextLine();
            userDouble = Double.parseDouble(input);
        }
        catch(NumberFormatException nfe) {
            System.out.println("I did not recognize your command, please try again.");
        }
        scan.close();
        return userDouble;
    }

    private void addItem() {
        String itemName = "";
        double price;
        int quantity;
        String namePrompt = "Enter the name of the item being added to the inventory: ";
        String pricePrompt = "Enter the cost of " + itemName + ": ";
        String quantityPrompt = "Enter the quantity of " + itemName + ": ";
        itemName = getUserString(namePrompt);
        price = getUserDouble(pricePrompt);
        quantity = getUserInt(quantityPrompt);
        controller.addItem(itemName, quantity, price);
    }




}


推荐答案

正如我在我的评论,问题是每次你做这样的事情你关闭 System.in

As I stated in my comment, the problem is that you're closing System.in each time you do something like this:


Scanner scan = new Scanner(System.in);
...
scan.close();


现在,看看 Scanner.nextLine

Now, look at the specification of Scanner.nextLine


投掷


  • NoSuchElementException - 如果没有找到行

  • IllegalStateException - 如果此扫描仪关闭

  • NoSuchElementException - if no line was found
  • IllegalStateException - if this scanner is closed

现在,因为扫描仪本身未关闭,将不会抛出 IllegalStateException 。相反,正如您之前提到的,抛出另一个例外,通常与找不到新行相关, - NoSuchElementException

Now, since the scanner itself is not closed, an IllegalStateException will not be thrown. Instead, as you mentioned before, the other exception, "typically related to not finding a new line", -- NoSuchElementException -- is thrown.

假设你正在使用JDK 7,你可以通过检查 Scanner.throwFor

Presuming this you're using JDK 7, you can see how this works by examining Scanner.throwFor:

if ((sourceClosed) && (position == buf.limit()))
    throw new NoSuchElementException();

由于抛出异常,值 0 getUserChar 返回,然后在 run 循环中使用:

Since your exception is thrown, a value of 0 is returned by getUserChar, which is then used in the run loop:


do{
      userInput = mainMenu();
      if(isUserInputValid(userInput))
        ...
      else System.out.println("\nMainMenu");
    } while(!(wantToQuit));


由于输入无效,您陷入了循环打印\ nMainMenu \ n

Since the input is invalid, you're caught in a loop printing "\nMainMenu\n".

要解决此问题,请尝试使用单个扫描仪并且不要关闭 System.in ; - )

To correct the issue, try to use a single Scanner and don't close System.in ;-)

这篇关于Java Scanner.nextLine()不等待输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆