Search code examples
javawhile-loopswitch-statementuser-inputnosuchelementexception

Why I can`t iterate through while function and how to fix it? I`m getting NoSuchElementException


I got a problem with my university task.

How to start program: type 1 to create a file then write down the name of text file and fill it with words. After that press enter 2 times and you will get my problem -> NoSuchElementException.

I tried to fix this problem by creating different types of loops or changing the structure of the project, but still don`t know how to fix it. I just stuck and wasted some time on this problem. If someone more knowledgeable could help me out it would be wonderful.

My code all in one class:

import java.io.*;
import java.util.Scanner;
import java.io.InputStreamReader;
public class Main {

    public static void main(String[] args) throws IOException {
        showMenu();
    }
    static void showMenu() throws IOException {
        menuOptions();
        Scanner scan = new Scanner(System.in);
        int userMenuInput = 0;
        if (scan.hasNextLine()) {
            try {
                userMenuInput = Integer.parseInt(scan.nextLine());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        while (true) {
            switch (userMenuInput) {
                case 1:
                    System.out.println("Create a file");
                    String userFileName = scan.nextLine();
                    createFile(userFileName + ".txt");
                    break;
                case 2:
                    System.out.println("Delete a file");
                    String userDeleteFile = scan.nextLine();
                    deleteFile(userDeleteFile);
                    break;
                case 3:
                    System.out.println("Write to a file");
                    break;
                case 4:
                    System.out.println("Exit from program");
                    System.exit(0);
                    break;
                default:
                    System.out.println("Please type from 1 to 4!");
            }
        }
    }


    private static void createFile(String fileName){
        System.out.println(System.getProperty("user.dir"));
        File myFile = new File(System.getProperty("user.dir") + "\\" + fileName);
        try {
            myFile.createNewFile();
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            // Create PrintWriter to write to file
            PrintWriter out = new PrintWriter(new FileWriter(myFile));
            String s;
            System.out.print("Enter text: ");
            while ((s = in.readLine()) != null && (s.length() != 0)) {
                out.println(s);
            }
            in.close();   // Close reader from input
            out.close();  // Close writer to file
        } catch (IOException e) {
            System.out.println("File writing failed!");
        }
        System.out.println(myFile.getAbsolutePath());

    }
    private static void deleteFile(String fileNameToDelete){
        try{
            System.out.println("Enter file name to delete: ");
            File sourceFile = new File(fileNameToDelete+".txt");

            sourceFile.delete();
        }
        catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
    private static void menuOptions(){
        System.out.println("Choose from these choices");
        System.out.println("-------------------------\n");
        System.out.println("1 - Create file");
        System.out.println("2 - Delete file");
        System.out.println("3 - Write to file");
        System.out.println("4 - Quit");
        System.out.println();
    }
}

Solution

  • to add to Ryans answer, the exception comes from the fact that closing any object making use of the input/output stream doesn't really close that object, but the entire input/output stream. A dirty fix would simply be NOT to close them. so change your method createFile from:

        private static void createFile(String fileName){
        System.out.println(System.getProperty("user.dir"));
        File myFile = new File(System.getProperty("user.dir") + "\\" + fileName);
        try {
            myFile.createNewFile();
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            // Create PrintWriter to write to file
            PrintWriter out = new PrintWriter(new FileWriter(myFile));
            String s;
            System.out.print("Enter text: ");
            while ((s = in.readLine()) != null && (s.length() != 0)) {
                out.println(s);
            }
            in.close();   // Close reader from input
            out.close();  // Close writer to file
        } catch (IOException e) {
            System.out.println("File writing failed!");
        }
        System.out.println(myFile.getAbsolutePath());
    
    }
    

    to:

        private static void createFile(String fileName){
        System.out.println(System.getProperty("user.dir"));
        File myFile = new File(System.getProperty("user.dir") + "\\" + fileName);
        try {
            myFile.createNewFile();
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            // Create PrintWriter to write to file
            PrintWriter out = new PrintWriter(new FileWriter(myFile));
            String s;
            System.out.print("Enter text: ");
            while ((s = in.readLine()) != null && (s.length() != 0)) {
                out.println(s);
            }
            //were close used to be
        } catch (IOException e) {
            System.out.println("File writing failed!");
        }
        System.out.println(myFile.getAbsolutePath());
    
    }
    

    I will stess that this is NOT ideal. You should do what Ryan said and make it so you only use use a single System.in reader. Doing that is your job, not mine. But if this is just to get something working so you can submit an assignment on time, it will work.

    Another issue is that the prompt asking for a menu option is outside of the while loop. This means that it will accept only one input, then get stuck in an infinite loop. You could move that into the loop, but a cleaner alternative is to put all of the menu logic into the menuOption method, pass a reference of the Scanner to that method, and have it return an int for your switch. for example:

    menuOption():

        private static int menuOptions(Scanner scan){
        System.out.println("Choose from these choices");
        System.out.println("-------------------------\n");
        System.out.println("1 - Create file");
        System.out.println("2 - Delete file");
        System.out.println("3 - Write to file");
        System.out.println("4 - Quit");
        System.out.println();
    
        
        if (scan.hasNextLine()) {
            try {
                return Integer.parseInt(scan.nextLine());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }
    

    showMenu():

        static void showMenu() throws IOException {
        Scanner scan = new Scanner(System.in);
        while (true) {
            switch (menuOptions(scan)) {
                case 1:
                    System.out.println("Create a file");
                    String userFileName = scan.nextLine();
                    createFile(userFileName + ".txt");
                    break;
                case 2:
                    System.out.println("Delete a file");
                    String userDeleteFile = scan.nextLine();
                    deleteFile(userDeleteFile);
                    break;
                case 3:
                    System.out.println("Write to a file");
                    break;
                case 4:
                    System.out.println("Exit from program");
                    System.exit(0);
                    break;
                default:
                    System.out.println("Please type from 1 to 4!");
            }
        }
    }
    

    all of those changes lead to this as the final code:

    import java.io.*;
    import java.util.Scanner;
    import java.io.InputStreamReader;
    public class Main {
    
    public static void main(String[] args) throws IOException {
        showMenu();
    }
    static void showMenu() throws IOException {
        Scanner scan = new Scanner(System.in);
        while (true) {
            switch (menuOptions(scan)) {
                case 1:
                    System.out.println("Create a file");
                    String userFileName = scan.nextLine();
                    createFile(userFileName + ".txt");
                    break;
                case 2:
                    System.out.println("Delete a file");
                    String userDeleteFile = scan.nextLine();
                    deleteFile(userDeleteFile);
                    break;
                case 3:
                    System.out.println("Write to a file");
                    break;
                case 4:
                    System.out.println("Exit from program");
                    System.exit(0);
                    break;
                default:
                    System.out.println("Please type from 1 to 4!");
            }
        }
    }
    
    
    private static void createFile(String fileName){
        System.out.println(System.getProperty("user.dir"));
        File myFile = new File(System.getProperty("user.dir") + "\\" + fileName);
        try {
            myFile.createNewFile();
            BufferedReader in = new BufferedReader(new 
            InputStreamReader(System.in));
            // Create PrintWriter to write to file
            PrintWriter out = new PrintWriter(new FileWriter(myFile));
            String s;
            System.out.print("Enter text: ");
            while ((s = in.readLine()) != null && (s.length() != 0)) {
                out.println(s);
            }
          //were close used to be
        } catch (IOException e) {
            System.out.println("File writing failed!");
        }
        System.out.println(myFile.getAbsolutePath());
    
    }
    private static void deleteFile(String fileNameToDelete){
        try{
            System.out.println("Enter file name to delete: ");
            File sourceFile = new File(fileNameToDelete+".txt");
    
            sourceFile.delete();
        }
        catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
    private static int menuOptions(Scanner scan){
        System.out.println("Choose from these choices");
        System.out.println("-------------------------\n");
        System.out.println("1 - Create file");
        System.out.println("2 - Delete file");
        System.out.println("3 - Write to file");
        System.out.println("4 - Quit");
        System.out.println();
    
        
        if (scan.hasNextLine()) {
            try {
                return Integer.parseInt(scan.nextLine());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }
    
    
    }
    

    Remember to close scan in your quit method.