Core Java

Closing Scanner Java Example

1. Introduction

The java.util.Scanner class can read input from System.in, File, InputStream, Path, Readable, String, etc. It implements the Closeable and AutoCloseable interfaces. The scanner close method will close its input source if the input source implements the Closeable interface. In this example, I will demonstrate how Eclipse IDE detects the resource leak and how to close a scanner in a Java project.

2. Setup

In this step, I will create a Java project in the Eclipse IDE with four files.

scanner close
Figure 1. Project Layout
  • ScannerDemoWithWarning.java – see step 3 for details.
  • CloseScannerViaTryDemo.java – see step 4 for details.
  • CloseScannerDemo.java – see step 5 for details.
  • CloseScannerTest.java – see step 5.1 for details.

Click the Eclipse IDE “Windows->Preferences” and navigate to “Java->Compiler->Errors/Warnings“. Find the “Resource leak:” and see that Eclipse IDE configures it as “Warning“.

scanner close
Figure 2. Eclipse Preferences for Resource Leak

3. ScannerDemoWithWarning

In this step, I will create a ScannerDemoWithWarning.java that creates a scanner from System.in and read a string via the nextLine method. The program exits without closing the scanner.

ScannerDemoWithWarning.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package org.zheng.demo;
 
import java.util.Scanner;
 
public class ScannerDemoWithWarning {
 
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Enter a name:");
 
        String name = scanner.nextLine();
        System.out.printf("Hello %s!", name);
    }
 
}

The Eclipse IDE shows a warning message: “Resource leak: 'scanner' is never closed“.

scanner close
Figure 3. Eclipse Detects Resource Leak

4. Scanner Close via Try-with-Resource

In this step, I will click the “Surround with try-with-resources” from the Eclipse IDE quick fix button.

scanner close
Figure 4. Eclipse Fix with Try-with-resources

Here is the fixed source code for ScannerDemoWithWarning.java.

Fixed ScannerDemoWithWarning.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
package org.zheng.demo;
 
import java.util.Scanner;
 
public class ScannerDemoWithWarning {
 
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            System.out.println("Enter a name:");
 
            String name = scanner.nextLine();
            System.out.printf("Hello %s!", name);
        }
    }
 
}
  • Line 8: the try-with-resources will automatically close the scanner.

5. Scanner Close

In this step, I will create a CloseScannerDemo.java class that creates a scanner from a text file and closes the scanner before the program exits.

CloseScannerDemo.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.zheng.demo;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
 
public class CloseScannerDemo {
 
    public static void main(String[] args) throws FileNotFoundException {
 
        File fileO = new File("C:\\MaryTools\\workspace\\CloseScannerDemo\\data.txt");
        Scanner scanner = new Scanner(fileO);
 
        String name = scanner.nextLine();
 
        System.out.printf("Hello %s!", name);
 
        scanner.close();
        // this does not close the File as File is not implements Closeable Interface,
        // so it will cause memory leak
    }
 
}
  • Line 11: File does not implement the Closeable interface, so after the scanner is closed, the file is not released. This will lead to file locking and memory leak issues.

Here is the text data file content.

data.txt content

1
Mary

Here is the updated CloseScannerDemo.java that will close the scanner and its FileInputStream as FileInputStream implements the Closeable interface.

Proper CloseScannerDemo.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
package org.zheng.demo;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
 
public class CloseScannerDemo {
 
    public static void main(String[] args) throws FileNotFoundException {
 
        File fileO = new File("C:\\MaryTools\\workspace\\CloseScannerDemo\\data.txt");
        try (Scanner scanner = new Scanner(new FileInputStream(fileO))) {
            String name = scanner.nextLine();
 
            System.out.printf("Hello %s!", name);
        }
 
    }
 
}
  • Line 13: try-with-resources with FileInputStream is better as it closes its input sources.

5.1 Scanner Close Test

In this step, I will create a CloseScannerTest.java that verifies the System.in is also closed when the scanner is closed. Therefore can not create another new scanner nor use the already closed scanner.

CloseScannerTest.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package org.zheng.demo;
 
import static org.junit.jupiter.api.Assertions.assertThrows;
 
import java.util.NoSuchElementException;
import java.util.Scanner;
 
import org.junit.jupiter.api.Test;
 
class CloseScannerTest {
 
    @Test
    void throwIllegalStateExceptionOnReuseClosedScanner() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Enter a name:");
 
        String name = scanner.nextLine();
        System.out.printf("Hello %s!", name);
 
        // add close at the last statement
        scanner.close();
        // The System.in is InputStream class that implements Closeable
        assertThrows(IllegalStateException.class, scanner::nextInt);
 
    }
 
    @Test
    void throwNoSuchElementExceptionOnNewScannerWithClosedSystemIn() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Enter a name:");
 
        String name = scanner.nextLine();
        System.out.printf("Hello %s!", name);
 
        // add close at the last statement
        scanner.close();// this close the System.in as it implements Closeable
        Scanner scanner2 = new Scanner(System.in);
        assertThrows(NoSuchElementException.class, scanner2::nextInt);
        scanner2.close();
    }
 
}
  • Line 23: IllegalStateException is thrown when accessing the already closed scanner.
  • Line 38: NoSuchElementException is thrown when accessing the scanner with closed System.in.

6. Conclusion

In this example, I demonstrated how Eclipse IDE detects the scanner-is-not-closed problem and how It provides a fix with try-with-resources. Scanner close via try-with-resources ensures automatic closure even if an exception occurs.

7. Download

This was an example of a Java project that includes scanner close examples.

Download
You can download the full source code of this example here: Closing Scanner Java Example

Mary Zheng

Mary graduated from the Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She worked as a lead Software Engineer where she led and worked with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button