user8746377
user8746377

Reputation:

Scanner Exception error?

The error should not have occurred as I have closed the Scanner object I declared in the registerN() function and declared a new one for setInfo() to use. But still, I kept getting the following output every time I input "register" as the value of option.

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Unknown Source)
    at Student.setInfo(student.java:37)
    at Group.registerN(student.java:87)
    at Manage.main(student.java:168)

This is the code,

import java.util.*;
import java.io.File;
import java.io.PrintWriter;

// **** Student details ****// 
class Student {
    // Identity description
    String name;
    char sex;
    int age;
    String id;
    // Educational description
    String department;

    void setInfo(){
        Scanner input = new Scanner(System.in);

        System.out.println("Please input the following information about the student...");
        System.out.print("Name:\t");
        name = input.nextLine();
        System.out.print("Sex:\t");
        sex = Character.toLowerCase(input.next().charAt(0));
        System.out.print("Age:\t");
        age = input.nextInt();
        System.out.print("Department:\t");
        department = input.nextLine();
        System.out.print("ID:\t");
        id = input.nextLine();

        input.close();
    }

}
// **** **** **** **** **** **** //


// **** Collection of the students **** //
class Group {
    ArrayList<Student> DB = new ArrayList<Student>();

    Student temp = new Student();

    void registerN(){
        Scanner input = new Scanner(System.in);
        System.out.print("How many students would you like to register: ");
        int n = input.nextInt();
        input.close();

        for(int i = 1; i <= n; ++i){
            temp.setInfo();
            DB.add(temp);
            System.out.println("Student(s) " + i + " out of " + n + " registered.");
        }
    }
}
//**** **** **** **** **** **** //

// **** A class to make use of the objects **** //
class Manage {

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        Group base = new Group();
        // option string
        String option = "";

        // I specify the options a user can input here

        while(true){
            System.out.print("option: ");
            option = input.nextLine();
            option = option.toLowerCase();

            if(option.equals("register")){
                base.registerN();
            }
            else
                System.out.println("\t\"" + option + "\" not recognized!\n\tReview options list.");
        }
        input.close();
    }
}

I put a breaking point at the point control is passed to the function base.registerN(); which in turn passes control to temp.setInfo(). But immediately after that happens and setInfo() prints out Please input the following information about the student... Name:, I get the error I put above. Why is that?

Upvotes: 1

Views: 308

Answers (2)

Vishnu T S
Vishnu T S

Reputation: 3914

Below method you have closed input stream by calling input.close();

void registerN(){
        Scanner input = new Scanner(System.in);
        System.out.print("How many students would you like to register: ");
        int n = input.nextInt();
        input.close();

If you call the method input.close() ,System.in will be closed. It wont accept any further input.

If you want to avoid this, create a global variable of scanner which can be used by all classes

System.in. was not instantiated by by your code, but by the JVM.

JVM will take care of closing it if needed.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726579

When you dispose of a Scanner by calling close() you can no longer read from its input stream, even if you construct a new Scanner around it. That is why closing the Scanner inside registerN method leads to an error inside setInfo method.

You should change the approach by passing one Scanner object around your code, rather than constructing one "on demand" inside setInfo method:

void setInfo(Scanner input){
    ...
    name = input.nextLine();
    ...
}

Also pass Scanner to registerN:

if(option.equals("register")){
    base.registerN(input);
}

This way you would use a single Scanner created in main, and never close it.

Upvotes: 0

Related Questions