Java Lesson 13: Input / Output Streams

1
32

Introduction

In Java Lesson 6: Simple Console Input / Output, we learned a couple ways to receive user input from the keyboard and to output to the display screen. Most programs also access disk drives, USB devices, and networks. We will learn how to use other popular classes that Java provides for I/O. This will enable us to write more useful and complex programs.

Review of Streams

streams2Recall that Java programs perform I/O through streams, which either produce or consume information. You can think of streams as a stream of water that either carries information to the computer or out of the computer. A stream connects to a physical device like a keyboard, a display, a printer, a disk file, or a network.

Preparing For Input / Output Operations

import Statements

Most I/O classes are in the java.io package, not in the java.lang package, so we need an import statement to tell the Java compiler where to find the libraries for these classes. The Java compiler will display an error message if you are missing an import statement it expects, so it is usually a simple matter to add the statement and recompile. Import statements go at the beginning of your program, immediately after a package statement if you have one. Common imports are:

Handling Exceptions

The Java compiler knows when exceptions are likely to occur when performing I/O, and it will force the developer to handle possible exceptions in one of two ways:

  1. Append a throws statement in the main() program declaration. This is the easiest way and acceptable for small example programs. Examine Program13a.java below for the proper placement of throws.
  2. Surround I/O statements with try-catch-finally blocks. This is a good practice so the error is dealt with gracefully.

If you do not handle the exception in some way then the Java compiler will not compile your program:

I will show both ways in the examples below. Review Java Lesson 12: Exceptions if you need a refresher.

Specifying Which File or Device to Open

Typically in your program you will specify a device name and a file name to open for reading or writing. We will see new (and strange-looking) statements such as these:

Contrary to what you may think, the first statement does not create a new file on your disk drive. Rather, it declares and creates a new object variable of the File class, just like new creates objects of other classes. For demonstration purposes it is common to use short variable names like file and fr which reflect the name of the class they derive from; however in real programs you may want to use more descriptive variable names such as inputFile or inventoryFile.

Specifying Folder Names

Different operating systems use different characters to represent directory or folder and subfolder names, such as:

  • Linux and Mac OS use the forward slash character “/” to separate folder names.
  • Windows uses the backslash character “\” to separate folder names.
  • Some operating systems are case-sensitive, so Dev may or may not be the same as dev.

Unfortunately, Java sees the backslash as an escape sequence for those occasions when you want to use \n and \t to insert a newline character or a tab. Two ways to specify folder names in Windows are:

  1. Prefix each backslash with another backslash so there are two backslashes.
  2. Use forward slashes instead of backslashes.

Thus, both of the following specify the same folders and file:

Closing a File

You should explicitly close files so the Java garbage collector recovers the resources (e.g., memory, locks) they consume. Use the .close() method for this purpose.

A Short Comment About Comments

As our programs become longer it is helpful to include comments after the closing curly brace “}” to make it easy to match the opening and closing curly brace pairs.

If your program won’t compile, carefully compare your programs with the examples below and double-check that you have one (and only one) closing brace for each opening brace.

Reading Files With BufferedReader

Our first example uses the four statements we saw above to prepare for I/O operations. File and FileReader open a text file, and BufferedReader reads the text file. It uses a while loop to read each line of text in the file until there are no more lines to read, and then displays the line on the console. To keep things simple Program13a.java uses a throws statement to throw any errors back to the JVM.

We will use these BufferedReader methods:

  .readLine()  Reads a String from the reader.
 .close()  Closes the reader and releases resources.

First, use your editor to create a file named textfile.txt with the following text in the same folder as your Java programs:

Then, create, compile, and run Program13a.java as shown below.

Compile and execution of Program13a.java which reads a text file.

As previously mentioned, lots of things can go wrong with file operations. Let’s see what happens if you misspell the file name or textfile.txt does not exist. Here I will delete the file and run Program13a again:

Execution of Program13a when the file does not exist.

The stacktrace shows Java threw a FileNotFoundException because the system cannot find the file specified in the program. The error happened in the open() method of FileInputStream called by FileReader called by line number 18 in the main() method of our program.

Although stacktraces are helpful to Java developers, they often look intimidating to users. This is why it is a good idea to surround I/O statements with try-catch or try-catch-finally blocks, as seen in Program13b.java:

Compile and execution of Program13b.java. The input file does not exist, but this time the program displays a user-friendly error message.

An exception still occurs if the input file does not exist, but with try-catch we can display a user-friendly error message.

Note: The code in Program13b is admittedly longer and more complex than in Program13a. Fortunately, Java SE 7 adds the try-with-resources statement which makes coding easier. Look for an example in a future Lesson or Snippet.

Writing Files With BufferedWriter

The converse of BufferedReader is BufferedWriter.

Our next example uses File and BufferedWriter to prepare for I/O operations. We will use these BufferedWriter methods:

  .write(String str)  Writes a String to the writer.
  .newline()  Writes a newline character to the writer.
  .flush()  Flushes the stream (forces output to the file).
  .close()  Closes the writer.

Program13c.java uses write() to send each line of text to the buffer, and newLine() to add a newline character to the end of each line. After writing three lines it flushes (forces) the buffer’s contents to the file and closes the file. If textfile.txt already exists then it will be overwritten.

Compile and execution of Program13c.java which creates a new text file and writes three lines to it.

Reading From the Internet With InputStreamReader

Two other common I/O classes are InputStreamReader and URLProgram13d.java uses URL to format a Uniform Resource Locator (an Internet address such as http://www.WikiProgramming.org) and InputStreamReader to read the HTML source code from the website. For efficiency it also introduces the StringBuilder class which is discussed in a future tutorial.

The screenshot below shows the final few lines from WikiProgramming.org’s home page and the number of characters on the page.

Execution of Program13d.java which shows the HTML code from WikiProgramming.org

Reading and Writing Data With Scanner and PrintStream

We previously used the Scanner class for console I/O, and it can also be used for file I/O. We also introduce the PrintStream class. Program13e.java opens an existing text file containing an integer number, adds 8 to the number, and writes the new value to the same file.

As with console I/O, the nextInt() method of Scanner reads the integer from the file.

First, use your editor to create a text file called ReadAndWriteDataFile.TXT, and then enter, compile, and run Program13e. You can put any integer into the file; I entered the number 2. You can give the file any name you want, but you use the same name in the program’s code.

Compile and execution of Program13e.java, which reads and updates an integer in a data file.

Summary

This tutorial lesson showed some popular ways to read and write data to disk files and the network. Java provides other I/O classes for special needs.

Next Lesson

Next we will move on to Threads.

 

1 COMMENT

  1. […] Exceptions can occur when performing Input/Output operations. Next we will move on to I/O Streams. […]

Leave a Reply