1

If I close one scanner object and make a new one and try to read some more input, I'm getting the NoSuchElementException exception.

My code works fine but it gives me a warning if I don't close the scanner. However, if I close it to get rid of the warning, I also close System.in... How do I avoid this?

Also, are there any consequences of not closing the scanner?

EDIT: Here's my code:

This is the NameAddressExists() method:

public void NameAddressExists() {
    System.out.println("Enter name");
    Scanner sc = new Scanner(System.in);
    String n = sc.next();
    System.out.println("Enter address");
    String a = sc.next();
    int flag = 0;
    for(int i = 0; i < count; i++) {
        if(array[i].name .equals(n) && array[i].address .equals(a)) {
            System.out.println("True");
            flag = 1;
        }
    }
    if(flag != 1) {
        new Agency(n, a);
    }
    sc.close();
}

This is the PanNumberExists() method:

public boolean PanNumberExists() {
    Scanner s = new Scanner(System.in);
    String n = "";
    System.out.println("Enter the 5 digits");
    try {
        n = s.nextLine();
    }catch(Exception e) {
        System.out.println(e);
    }finally {
        s.close();
    }
    if(n  .equals(this.PAN.subSequence(4,9))) {
        return true;
    }
    else {
        return false;
    }
}

These methods are called from the following main() method:

public static void main(String args[]) {
    Agency obj1 = new Agency("XYZ", "ABCD");
    Agency obj2 = new Agency("XYZ", "ABCDEFG", "+91083226852521", "ab 1234567", "abcd12345ab");
    // Agency obj3 = new Agency("XYZ", "TSRK", "36", "ab 1234567", "abcd12345ab");
    obj1.NameAddressExists();
    System.out.println(obj2.PanNumberExists());
}

As you can see, I first call the NameAddressExists() method, in which I open, use and close a Scanner named 'sc'. This works fine and gives me the correct output. Next, I call the PanNumberExists() method, in which I open another Scanner named 's' and try to use it to get some input from the user. This is where I receive the NoSuchElementException exception. If I leave the Scanner 'sc' open in my NameAddressExists() method, then I don't get this error.

Akshay Damle
  • 1,220
  • 3
  • 18
  • 31
  • 1
    Something else is wrong, seeing your code would make the problem easier to diagnose. – Hunter McMillen Aug 26 '14 at 12:51
  • 1
    That's not normal behavior. Can you show your code? As for not closing the Scanner – at the risk of getting shot at by other users – it's no big deal if your program isn't big. But it's nice to close things you open to manage the memory. – ljacqu Aug 26 '14 at 12:51
  • Just close the Scanner at the very end of the program in a finally block and you're golden. – EpicPandaForce Aug 26 '14 at 12:53
  • Also, can you provide JDK version and OS ? – ortis Aug 26 '14 at 12:54

1 Answers1

0

You can use the Decorator pattern and create custom InputStream that can't be closed, then pass it to the Scanner

import java.io.IOException;
import java.io.InputStream;

public class PreventClosingInputStream extends InputStream {

    private InputStream inputStream;

    public PreventClosingInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    @Override
    public int read() throws IOException {
        return inputStream.read();
    }

    @Override
    public void close() throws IOException {
        // Don't call super.close();
    }

}

Then, in your code:

PreventClosingInputStream in = new PreventClosingInputStream(System.in);
Scanner s = new Scanner(in);
// ...
s.close(); // This will never close System.in as there is underlying PreventClosingInputStream with empty close() method

Using try-with-resources:

try (PreventClosingInputStream in = new PreventClosingInputStream(System.in);
        Scanner s = new Scanner(in);) {
    // ...
    // resources will be automatically closed except of System.in
}
jjurm
  • 501
  • 6
  • 11