Chapter: Java The Complete Reference - The Java Language - I/O, Applets, and Other Topics

| Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail |

Automatically Closing a File - java

In the preceding section, the example programs have made explicit calls to close( ) to close a file once it is no longer needed.

Automatically Closing a File

 

In the preceding section, the example programs have made explicit calls to close( ) to close a file once it is no longer needed. As mentioned, this is the way files were closed when using versions of Java prior to JDK 7. Although this approach is still valid and useful, JDK 7 added a new feature that offers another way to manage resources, such as file streams, by automating the closing process. This feature, sometimes referred to as automatic resource management, or ARM for short, is based on an expanded version of the try statement. The principal advantage of automatic resource management is that it prevents situations in which a file (or other resource) is inadvertently not released after it is no longer needed. As explained, forgetting to close a file can result in memory leaks, and could lead to other problems.

Automatic resource management is based on an expanded form of the try statement. Here is its general form:

 

try (resource-specification) { // use the resource

}

 

Here, resource-specification is a statement that declares and initializes a resource, such as a file stream. It consists of a variable declaration in which the variable is initialized with a reference to the object being managed. When the try block ends, the resource is automatically released. In the case of a file, this means that the file is automatically closed. (Thus, there is no need to call close( ) explicitly.) Of course, this form of try can also include catch and finally clauses. This new form of try is called the try-with-resources statement.

 

The try-with-resources statement can be used only with those resources that implement the AutoCloseable interface defined by java.lang. This interface defines the close( ) method. AutoCloseable is inherited by the Closeable interface in java.io. Both interfaces are implemented by the stream classes. Thus, try-with-resources can be used when working with streams, including file streams.

 

As a first example of automatically closing a file, here is a reworked version of the ShowFile program that uses it:

 

/*        This version of the ShowFile program uses a try-with-resources statement to automatically close a file after it is no longer needed.

 

Note: This code requires JDK 7 or later.

 

*/

 

import java.io.*;

 

class ShowFile {

 

public static void main(String args[])

 

{

 

int i;

 

     First, confirm that a filename has been specified.

     if(args.length != 1) {

 

System.out.println("Usage: ShowFile filename"); return;

 

}

 

     The following code uses a try-with-resources statement to open

 

     a file and then automatically close it when the try block is left.

 

     try(FileInputStream fin = new FileInputStream(args[0])) {

 

do {

 

i = fin.read();

 

if(i != -1) System.out.print((char) i);

 

} while(i != -1);

 

} catch(FileNotFoundException e) {

System.out.println("File Not Found.");

} catch(IOException e) {

System.out.println("An I/O Error Occurred");

 

}

 

}

 

}

 

In the program, pay special attention to how the file is opened within the try statement:

 

try(FileInputStream fin = new FileInputStream(args[0])) {

 

Notice how the resource-specification portion of the try declares a FileInputStream called fin, which is then assigned a reference to the file opened by its constructor. Thus, in this version of the program, the variable fin is local to the try block, being created when the try is entered. When the try is left, the stream associated with fin is automatically closed by an implicit call to close( ). You don’t need to call close( ) explicitly, which means that you can’t forget to close the file. This is a key advantage of using try-with-resources.

It is important to understand that the resource declared in the try statement is implicitly final. This means that you can’t assign to the resource after it has been created. Also, the scope of the resource is limited to the try-with-resources statement.

You can manage more than one resource within a single try statement. To do so, simply separate each resource specification with a semicolon. The following program shows an example. It reworks the CopyFile program shown earlier so that it uses a single try-with-resources statement to manage both fin and fout.

 

/* A version of CopyFile that uses try-with-resources.

 

It demonstrates two resources (in this case files) being managed by a single try statement.

 

*/

 

import java.io.*;

 

class CopyFile {

 

public static void main(String args[]) throws IOException

 

{

 

int i;

 

     First, confirm that both files have been specified.

     if(args.length != 2) {

 

System.out.println("Usage: CopyFile from to"); return;

 

}

 

     //Open and manage two files via the try statement.

 

try (FileInputStream fin = new FileInputStream(args[0]);

FileOutputStream fout = new FileOutputStream(args[1]))

{

 

do {

 

i = fin.read();

 

if(i != -1) fout.write(i); } while(i != -1);

 

} catch(IOException e) {

System.out.println("I/O Error: " + e);

}

 

}

 

}

 

In this program, notice how the input and output files are opened within the try block:

 

try (FileInputStream fin = new FileInputStream(args[0]);

FileOutputStream fout = new FileOutputStream(args[1]))

{

 

// ...

 

After this try block ends, both fin and fout will have been closed. If you compare this version of the program to the previous version, you will see that it is much shorter. The ability to streamline source code is a side-benefit of automatic resource management.

There is one other aspect to try-with-resources that needs to be mentioned. In general, when a try block executes, it is possible that an exception inside the try block will lead to another exception that occurs when the resource is closed in a finally clause. In the case of a “normal” try statement, the original exception is lost, being preempted by the second exception. However, when using try-with-resources, the second exception is suppressed. It is not, however, lost. Instead, it is added to the list of suppressed exceptions associated with the first exception. The list of suppressed exceptions can be obtained by using the getSuppressed( ) method defined by Throwable.

 

Because of the benefits that the try-with-resources statement offers, it will be used by many, but not all, of the example programs in this edition of this book. Some of the examples will still use the traditional approach to closing a resource. There are several reasons for this. First, there is legacy code that still relies on the traditional approach. It is important that all Java programmers be fully versed in, and comfortable with, the traditional approach when maintaining this older code. Second, because not all project development will immediately switch to a new version of the JDK, it is likely that some programmers will continue to work in a pre-JDK 7 environment for a period of time. In such situations, the expanded form of try is not available. Finally, there may be cases in which explicitly closing a resource is more appropriate than the automated approach. For these reasons, some of the examples in this book will continue to use the traditional approach, explicitly calling close( ). In addition to illustrating the traditional technique, these examples can also be compiled and run by all readers in all environments.


Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.