You are on page 1of 7

The RandomAccessFile Class

The stream classes just described operate on files in a strictly sequential fashion. However, Java also allows
you to access the contents of a file in non-sequential order. To do this, you will use RandomAccessFile,
which encapsulates a random-access file. RandomAccessFile is not derived from InputStream or
OutputStream. Instead, it implements the interfaces DataInput and DataOutput (which are described
shortly). RandomAccessFile supports random access because it lets you change the location in the file at
which the next read or write operation will occur. This is done by calling its seek( ) method.

Table 3.4 The Methods Defined by Reader


Method Description

abstract void close( ) throws


Closes the input source.
IOException

Places a mark at the current point in the input stream that will
void mark(int numChars)
remain valid until numChars characters are read. Not all streams
throws IOException
support mark( ).

boolean markSupported( ) Returns true if mark( )/reset( ) are supported on this stream.

Returns an integer representation of the next available character


int read( ) throws
from the input stream. –1 is returned when the end of the file is
IOException
encountered.

Attempts to read up to buffer.length characters into buffer and


int read(char buffer[ ])
returns the actual number of characters that were successfully read.
throws IOException
–1 is returned when the end of the file is encountered.

abstract int read(char


buffer[ ], Attempts to read up to numChars characters into buffer starting at
int offset, buffer[offset], returning the number of characters successfully read.
int numChars) –1 is returned when the end of the file is encountered.
throws IOException

boolean ready( ) throws


Returns true if input is pending. Otherwise, it returns false.
IOException

void reset( ) throws Resets the input pointer to the previously set mark. Not all streams
IOException support reset( ).

long skip(long numChars) Skips over numChars characters of input, returning the number of
throws IOException characters actually skipped.

The File Class


In addition to the classes that support file I/O, Java provides the File class, which encapsulates information
about a file. This class is extremely useful when manipulating a file itself (rather
than its contents) or the file system of the computer. For example, using File you can determine if a file is
hidden, set a file’s date, set a file to read-only, list the contents of a directory, or create a new directory,
among many other things. Thus, File puts the file system under your control. This makes File one of the
most important classes in Java’s I/O system.

Table 3.5 The Methods Defined By Writer


Method Description

Writer append(char ch) Appends ch to the end of the invoking output stream. Returns a
throws IOException reference to the stream.

Writer
append(CharSequence Appends chars to the end of the invoking output stream. Returns a
chars) reference to the stream.
throws IOException

Writer
append(CharSequence
Appends a subrange of chars, specified by begin and end, to the end
chars,
of the output stream. Returns a reference to the stream.
int begin, int end)
throws IOException

abstract void close( ) throws


Closes the output stream.
IOException

abstract void flush( ) throws Finalizes the output state so that any buffers are cleared. That is, it
IOException flushes the output buffers.

void write(int ch) throws Writes the character in the low-order 16 bits of ch to the output
IOException stream.

void write(char buffer[ ])


Writes a complete array of characters to the output stream.
throws IOException

abstract void write(char


buffer[ ],
Writes a subrange of numChars characters from the array buffer,
int offset,
beginning at buffer[offset] to the output stream.
int numChars)
throws IOException

void write(String str) throws


Writes str to the output stream.
IOException

void write(String str, int


Writes a subrange of numChars characters from the string str,
offset,
beginning at the specified offset.
int numChars)

The I/O Interfaces


Java’s I/O system includes the following interfaces (which are packaged in java.io):
Closeable DataInput DataOutput

Externalizable FileFilter FilenameFilter

Flushable ObjectInput ObjectInputValidation

ObjectOutput ObjectStreamConstants Serializable

Those used either directly or indirectly by the recipes in this chapter are DataInput, DataOutput, Closeable,
Flushable, FileFilter, FilenameFilter, ObjectInput, and ObjectOutput.

The DataInput and DataOutput interfaces define a variety of read and write methods, such as readInt( ) and
writeDouble( ), that can read and write Java’s primitive data types. They also specify read( ) and write( )
methods that parallel those specified by InputStream and OutputStream. All operations are byte-oriented.
RandomAccessFile implements the DataInput and the DataOutput interfaces. Thus, random-access file
operations in Java are byte-oriented.

Table 3.6 The Character Stream Classes


Method Description

BufferedReader Buffered input character stream.

BufferedWriter Buffered output character stream.

CharArrayReader Input stream that reads from a character array.

CharArrayWriter Output stream that writes to a character array.

FileReader Input stream that reads from a file.

FileWriter Output stream that writes to a file.

FilterReader Filtered reader.

FilterWriter Filtered writer.

InputStreamReader Input stream that translates bytes to characters.

LineNumberReader Input stream that counts lines.

OutputStreamWriter Output stream that translates characters to bytes.

PipedReader Input pipe.

PipedWriter Output pipe.

PrintWriter Output stream that contains print( ) and println( ).

Input stream that allows characters to be returned to the input


PushbackReader
stream.
Reader Abstract class that describes character stream input.

StringReader Input stream that reads from a string.

StringWriter Output stream that writes to a string.

Writer Abstract class that describes character stream output.

The Closeable and Flushable interfaces are implemented by several of the I/O classes. They provide a
uniform way of specifying that a stream can be closed or flushed. The Closeable interface defines only one
method, close( ), which is shown here:

void close( ) throws IOException

This method closes an open stream. Once closed, the stream cannot be used again. All I/O classes that
open a stream implement Closeable.
The Flushable interface also specifies only one method, flush( ), which is shown here:

void flush( ) throws IOException

Calling flush( ) causes any buffered output to be physically written to the underlying device. This interface is
implemented by the I/O classes that write to a stream.
FileFilter and FilenameFilter are used to filter directory listings.

The ObjectInput and ObjectOutput interfaces are used when serializing (saving and restoring) objects.

The Compressed File Streams


In java.util.zip, Java provides a very powerful set of specialized file streams that handle the compression and
decompression of data. All are subclasses of either InputStream or OutputStream, described earlier. The
compressed file streams are shown here:

DeflaterInputStream Reads data, compressing the data in the process.

DeflaterOutputStream Writes data, compressing the data in the process.

GZIPInputStream Reads a GZIP file.

GZIPOutputStream Writes a GZIP file.

InflaterInputStream Reads data, decompressing the data in the process.

InflaterOutputStream Writes data, decompressing the data in the process.

ZipInputStream Reads a ZIP file.


ZipOutputStream Writes a ZIP file.

Using the compressed file streams, it is possible to automatically compress data while writing to a file or to
automatically decompress data when reading from a file. You can also create compressed files that are
compatible with the standard ZIP or GZIP formats, and you can decompress files in those formats. The
actual compression is provided by the Inflater and Deflater classes, also packaged
in java.util.zip. They use the ZLIB compression library. You won’t usually need to deal with these classes
directly when compressing or decompressing files because their default operation is sufficient.

Tips For Handling Errors


File I/O poses a special challenge when it comes to error handling. There are two reasons for this. First, I/O
failures are a very real possibility when reading or writing files. Despite the fact that computer hardware (and
the Internet) is much more reliable than in the past, it still fails at a fairly high rate, and any such failure must
be handled in a manner consistent with the needs of your application. The second reason that error handling
presents a challenge when working with files is that nearly all file operations can generate one or more
exceptions. This means that nearly all file handling code must take place within a try block.

The most common I/O exception is IOException. This exception can be thrown by many of the constructors
and methods in the I/O system. As a general rule, it is generated when something goes wrong when reading
or writing data, or when opening a file. Other common I/O-related exceptions, such as
FileNotFoundException and ZipException, are subclasses of IOException.

There is another common exception related to file handling: SecurityException. Many constructors or
methods will throw a SecurityException if the invoking application does not have permission to access a file
or perform a specific operation. You will need to handlethis exception in a manner appropriate to your
application. For simplicity, the examples in
this chapter do not handle security exceptions, but it may be necessary for your applications to do so.

Because so many constructors and methods can generate an IOException, it is not uncommon to see code
that simply wraps all I/O operations within a single try block and then catches any IOException that may
occur. While adequate for experimenting with file I/O or possibly for simple utility programs that are for your
own personal use, this approach is not usually suitable for commercial code. This is because it does not let
you easily deal individually with each potential error. Instead, for detailed control, it is better to put each
operation within its own try block. This way, you can precisely report and respond to the error that occurred.
This is the approach demonstrated by the examples in this chapter.

Another way that IOExceptions are sometimes handled is by throwing them out of the method in which they
occur. To do this you must include a throws IOException clause in the method’s declaration. This approach
is fine in some cases, because it reports an I/O failure back to the caller. However, in other situations it is a
dissatisfying shortcut because it causes all users of the method to handle the exception. The examples in
this chapter do not use this approach. Rather, they handle all IOExceptions explicitly. This allows each error
handler to report precisely the error that occurred.

If you do handle IOExceptions by throwing them out of the method in which they occur, you must take extra
care to close any files that have been opened by the method. The easiest way to do this is to wrap your
method’s code in a try block and then use a finally clause to close the files(s) prior to the method returning.

In the examples in this chapter, any I/O exceptions that do occur are handled by simply displaying a
message. While this approach is acceptable for the example programs, real applications will usually need to
provide a more sophisticated response to an I/O error. For example, you might want to give the user the
ability to retry the operation, specify an alternative operation, or otherwise gracefully handle the problem.
Preventing the loss or corruption of data is a primary goal. Part of being a great programmer is knowing how
to effectively manage the things that might go wrong when an I/O operation fails.

One final point: a common mistake that occurs when handling files is forgetting to close a file when you are
done with it. Open files use system resources. Thus, there are limits to the
number of files that can be open at any one time. Closing a file also ensures that any data written to the file
is actually written to the physical device. Therefore, the rule is very simple: if you open a file, close the file.
Although files are typically closed automatically when an application ends, it’s best not to rely on this
because it can lead to sloppy programming and bad habits. It is better to explicitly close each file, properly
handling any exceptions that might occur. For this reason, all files are explicitly closed by the examples in
this chapter, even when the program is ending.

Write to file

At this point we have a writer object and we can send real content to the file. You can do this
using the write() method, which has more variant but the most commonly used requires a
string as input parameter.

Calling the write() method doesn't mean that it immediately writes the data into the file. The
output is maybe cached so if you want to send your data immediately to the file you need to
call the flush() method.

As last step you should close the file with the close() method and you are done.

The basic write method looks like this:

Code:

1. public void writeFile() {


2. String fileName = "c:\\test.txt";
3.
4. try {
5. FileWriter writer = new FileWriter(fileName,true);
6. writer.write("Test text.");
7. writer.close();
8. } catch (IOException e) {
9. e.printStackTrace();
10. }
11.}
12.

Java F1

However in a real world situation the FileWriter usually not used directly. Instead of FileWriter
the BufferedWriter or from Java 1.5 the PrintWriter are used. These writer objects gives you
more flexibility to handle your IO. Here is a simple BufferedWriter example:
Code:

1. public void writeFile() {


2. String fileName = "c:\\test.txt";
3.
4. try {
5. BufferedWriter writer = new BufferedWriter(new
FileWriter(fileName,true));
6. writer.write("Test text.");
7. writer.newLine();
8. writer.write("Line2");
9. writer.close();
10. } catch (IOException e) {
11. e.printStackTrace();
12. }
13.}

Java F1

You might also like