Widget Identifiers and Automatic Resource Management (ARM)

Overview

Recently, I had a requirement to validate a text file containing a list of identifiers. Lets call them ‘Widget Identifiers’. A valid Widget Identifier consists of an integer number only, anything else is invalid. The task was to read in the list of identifiers and, depending on whether the identifier was valid or not, write to one of two output files.

So we have three text files.

  1. An input file containing our Widget Identifiers.
  2. An output file containing valid identifiers.
  3. An output file containing invalid identifiers (if any).

A sample input file looks something like:

 1902
 5499
 9z86 (invalid)
 43k3 (invalid)
 8030
 4124
 6029
 2494
 8059
 6754 

Where rows 3 and 4 constitute invalid identifiers.

Details

There are various ways of accomplishing this task, but I wrote a Java program using a regular-expression construct (POSIX character classes) from the class java.util.regex.Pattern. The character class ‘\p{Alpha}’ is a class of alphabetic characters, so I used this to match for any invalid identifiers. In the above sample input file, lines 3 and 4 would be matched (found) and be written to the invalid rejects file. If a match was not fund, this was considered to be a valid identifier and therefore written to the ‘valid identifiers’ text file. As a further tidy-up, I chose to ensure leading and trailing white-space were omitted by using the ‘trim’ method from the java.lang.String class.

On dealing with text files for input and output, I chose to use the standard BufferedReader and BufferedWriter classes. It was during this time that I became aware of the recent construct addition to Java 1.7 of Automatic Resource Management (ARM) or try-with-resources.

Briefly, this is:

A try-with-resources statement has a resource specification that expresses resources to be automatically closed at the end of the Block. A resource specification declares one or more local variables and/or has one or more expressions, each of whose type must be a subtype of AutoCloseable or a compile-time error occurs.

This sounded useful, so I carried out some learning in order to incorporate this idea into the program I was writing.

Code details

I used the class java.nio.file.FileSystems to set my input and output paths. Because of this, a string variable was used to form the basepath.

final String BASEPATH="C:/junk";
Path inpath = FileSystems.getDefault().getPath(BASEPATH, "testinput.txt");
Path outpath = FileSystems.getDefault().getPath(BASEPATH, "goodoutput.txt");
Path badpath = FileSystems.getDefault().getPath(BASEPATH, "rejectedoutput.txt");

Meaning that all of the files used in this example were located in the directory C:/junk.

Using try-with-resources, the start of the try-catch block looks like:

 try (
   BufferedReader buffin = Files.newBufferedReader(inpath, Charset.forName("US-ASCII"));
   BufferedWriter buffout = Files.newBufferedWriter(outpath, Charset.forName("US-ASCII"));
   BufferedWriter badout = Files.newBufferedWriter(badpath, Charset.forName("US-ASCII"))
 )

with lines 2 to 4 being the resources used.

The complete try-catch block became:

 try (
    BufferedReader buffin = Files.newBufferedReader(inpath, Charset.forName("US-ASCII"));
    BufferedWriter buffout = Files.newBufferedWriter(outpath, Charset.forName("US-ASCII"));
    BufferedWriter badout = Files.newBufferedWriter(badpath, Charset.forName("US-ASCII"))
 )
 {
   inrec = buffin.readLine();
   while (inrec != null) {
     outrec=inrec.trim();
     match=patt.matcher(outrec);

     if (match.find()) {
       // This is a rejected record.
       System.out.printf("Rejected record = %s%n", outrec);
       badout.write(outrec);
       badout.newLine();
       badCount++;

     } else {
       // This is a good record.
       buffout.write(outrec);
       buffout.newLine();
       goodCount++;

     }

     inrec = buffin.readLine();
   }//end of while loop

 } catch (Exception e) {
     e. printStackTrace();
   } finally {
     System.out.println("All done now!");
 }

On exit from the try-catch block, our resources will be closed for us. If you code an explicit call to the close() statement by mistake, then you should see the following error message at compile time.

warning: [try] explicit call to close() on an auto-closeable resource

This will remind you that you don’t need to call the close() method.

As we’ve been using classes from the java.util.regex package, declarations using the Matcher and Pattern classes are:

final String patternStr="\\p{Alpha}";
Pattern patt = Pattern.compile(patternStr);
Matcher match = null;

Summary

The convenience of Automatic Resource Management means that you don’t have to worry about having to close your input/output streams. Any object that implements java.lang.AutoCloseable can be used as a resource. One disadvantage is that if you wanted to use any of these resources in a later part of the program, they’ve been closed and you can no longer use them. This means that you’d have to use a different implementation for these streams and perhaps having to close them the old fashioned way.

See also

Project Coin: Updated ARM Spec

Project Coin: Try out try-with-resources

Proposal: Automatic Resource Management

The try-with-resources Statement. The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.

Better Resource Management with Java SE 7: Beyond Syntactic Sugar By Julien Ponge.

 

Advertisements
This entry was posted in java and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s