Professional Documents
Culture Documents
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.
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.
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.
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 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.
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.
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:
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:
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.
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.
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.
Code:
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:
Java F1