简体   繁体   English

在 switch 语句中读取用户输入时出现 java.util.NoSuchElementException

[英]java.util.NoSuchElementException when reading user input in switch statement

Running into an error with this project I'm working on for a computer science course, and hoping someone can give me insight into what may be happening.我正在为计算机科学课程工作的这个项目遇到错误,希望有人能让我深入了解可能发生的事情。 A bit of background to what's occurring in the code:代码中发生的一些背景知识:

In the below code, I have the start of my program which displays a UI menu and asks for user input and uses a switch statement to run appropriate methods based on user input.在下面的代码中,我启动了我的程序,它显示一个 UI 菜单并要求用户输入,并使用 switch 语句根据用户输入运行适当的方法。

    /**
     * Start of program
     */
    public static void main(String[] args) {

        Library library = new Library();

        char userChoice; //Stores what menu item the user chose
        Scanner userMenuChoiceScanner = new Scanner(System.in);
        boolean loop = true;

        displayMenu(); //Displays main UI menu
        userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0)); //Gets user's menu choice

        /*Loops UI menu afer user has made menu choice and exits loop if user choses 'q' from menu.*/
        while(loop) {

            /* Switch descides what menu choice user has made and whether to prin menu UI again, load, 
             * search, print, or analyze a music catalog, or to quit program.
             */
            switch(userChoice) {
            case 'm':
                System.out.println();
                displayMenu();
                userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
                break;
            case 'p':
                System.out.println();

                if(library.getBooks().size() != 0) {
                    printLibrary(library);
                } else {
                    System.out.println("There are no books in the library. Please add a book first.");
                }

                System.out.print("Please enter a command (press 'm' for Menu):");
                userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
                break;
            case 'a':
                System.out.println();
                addBookToLibrary(library);
                System.out.print("Please enter a command (press 'm' for Menu):");
                userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
                break;
            case 'd':

                System.out.println();

                if(library.getBooks().size() != 0) {
                    deleteBookFromLibrary(library);
                } else {
                    System.out.println("There are no books in the library. Please add a book first.");
                }

                System.out.print("Please enter a command (press 'm' for Menu):");
                userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
                break;
            case 'r':           
                System.out.println();

                if(library.getBooks().size() != 0) {
                    readBookFromLibrary(library);
                } else {
                    System.out.println("There are no books in the library. Please add a book first.");
                }

                System.out.print("Please enter a command (press 'm' for Menu):");
                userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
                break;
            case 'q':
                System.out.println();
                System.out.println("Thank you! Goodbye!");
                loop = false;
                break;
            default:
                System.out.println();
                System.out.println("Invalid selection!");
                System.out.print("Please enter a command (press 'm' for Menu):");
                userChoice = Character.toLowerCase(userMenuChoiceScanner.nextLine().charAt(0));
                System.out.println();

            }
        }

        userMenuChoiceScanner.close();



    }

What's occuring is when tthe user makes a choice, it goes into the appropriate methods and fulfills it's tasks there, then when it returns to the switch statement to get a new user input, it throws a java.util.NoSuchElementException error as if the scanner stream was closed, but I don't close the scanner until the end (the stream should still be open).发生的情况是,当用户做出选择时,它会进入适当的方法并在那里完成任务,然后当它返回到 switch 语句以获取新的用户输入时,它会抛出java.util.NoSuchElementException错误,就像扫描仪一样stream 已关闭,但我直到最后才关闭扫描仪(stream 仍应打开)。

The switch statement is set up in a way where a book must be added (the user must chose 'a' first) before any other option can be chosen. switch 语句的设置方式是必须先添加一本书(用户必须先选择“a”),然后才能选择任何其他选项。 Here is the code to he addBookToLibrary() method which has a couple scanners which are opened and closed.这是addBookToLibrary()方法的代码,该方法有几个打开和关闭的扫描仪。 I assume maybe closing out these scanners may be causing the issue?我想也许关闭这些扫描仪可能会导致问题?

    /**
     * Adds new book to library
     * @param library ArrayList object which holds book objects
     */
    public static void addBookToLibrary(Library library) {
        Scanner addBookScanner = new Scanner(System.in);
        String title = "";
        String author = "";
        String genre = "";
        String filename = "";
        boolean addStatus = false;


        /*Asks user for book details */
        System.out.println("Enter the details of the book you want to add to the library:");
        System.out.println("What is the book title?");
        title = addBookScanner.nextLine();
        System.out.println("What is the author's name?");
        author = addBookScanner.nextLine();
        System.out.println("What is book genre?");
        genre = addBookScanner.nextLine();
        System.out.println("What is the book's filename?");
        filename = addBookScanner.nextLine();
        addBookScanner.close();

        Book newBook = new Book(author, title); //creates new book with author and title set

        newBook.setGenre(genre); //sets book genre

        File bookFile = new File(System.getProperty("user.dir") + '\\' + filename); //used to check if file user provided exists
        System.out.println(bookFile);
        /*Checks to see if file user provided actually exists*/
        if(bookFile.exists()) {

            try {

                newBook.setFilename(filename);

            }catch(Exception e) {

            }

        }
        else {

            Scanner getNewFilenameScanner = new Scanner(System.in);

            //Continues to ask user for new filename if file doesn't exist
            do {
            System.out.println("I'm sorry, but the file you specified does not exist.");
            System.out.print("Enter a new file name:");
            bookFile = new File(getNewFilenameScanner.nextLine());

            }while (!(bookFile.exists()));

            getNewFilenameScanner.close();
        }

        addStatus = library.addBook(newBook); //adds book to library

        if(addStatus) {
            System.out.println("Book was successfully added!");
        }
        else {
            System.out.println("Book was not successfully added. Please try again.");
        }
    }

This code worked perfectly in a previous project, so I'm not certain why it's not working now.这段代码在以前的项目中运行良好,所以我不确定为什么它现在不起作用。 Any help would be greatly appreciated.任何帮助将不胜感激。

Thank you so much太感谢了

In your addBookToLibrary method, you close the Scanner s after you are done using them.在您的addBookToLibrary方法中,您在使用完Scannerclose它们。 However, those scanners are connected to System.in , the standard input stream.但是,这些扫描仪连接到System.in ,标准输入 stream。 Closing those scanners will also close the standard input stream, according to the documentation .根据文档,关闭这些扫描仪也将关闭标准输入 stream。

What else is connected to the standard input stream?还有什么连接到标准输入stream? userMenuChoiceScanner , After the standard input stream is closed, userMenuChoiceScanner can't read from it, hence throwing an exception. userMenuChoiceScanner ,标准输入 stream 关闭后, userMenuChoiceScanner无法读取,因此抛出异常。

Note that although userMenuChoiceScanner is not closed until the very end, the stream that it is reading from is closed.请注意,虽然userMenuChoiceScanner直到最后才关闭,但它正在读取的 stream 已关闭。

In fact, you don't need to create multiple scanners here.事实上,您不需要在这里创建多个扫描仪。 You only need to use one scanner, and pass it around to different methods.您只需要使用一台扫描仪,并将其传递给不同的方法。 For example, addBookToLibrary could accept a Scanner :例如, addBookToLibrary可以接受Scanner

public static void addBookToLibrary(Library library, Scanner s) {

And it will only use s to read inputs.它只会使用s来读取输入。 You can pass your userMenuChoiceScanner to it:您可以将您的userMenuChoiceScanner传递给它:

addBookToLibrary(library, userMenuChoiceScanner);

As a general rule, you should not close anything that is not opened by you.作为一般规则,您不应该关闭任何不是您打开的东西。 You didn't open the standard input stream (the JVM did), so you shouldn't close it.您没有打开标准输入 stream(JVM 已打开),因此您不应关闭它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM