3.9 Random Access to Files

The examples we've seen so far have all read or written file content using streams. Streams provide sequential access to data and are particularly useful for network applications, which are often stream-oriented. Files stored on modern hard disks (as opposed to streaming tape drives) need not be accessed sequentially, and Java provides random access to files with the RandomAccessFile class. Example 3-8 demonstrates the use of random-access files by defining a list of strings stored in a file, along with an index to the position of each string. Note the use of writeInt( ), writeLong( ), and writeUTF( ) to write integers, longs, and strings, and the use of readInt( ), readLong( ), and readUTF( ) to read the corresponding values back. These methods are defined by the DataOutput and DataInput interfaces, which are also implemented by the DataOutputStream and DataInputStream classes. Note also the use of the seek( ) method to set the file position of a RandomAccessFile and the getFilePosition( ) method for querying the current position. Finally, don't forget that, like streams, random-access files must be closed when they are no longer needed.

Example 3-8. WordList.java
package je3.io; import java.io.*; /**  * This class represents a list of strings saved persistently to a file,   * along with an index that allows random access to any string in the list.  * The static method writeWords( ) creates such an indexed list in a file.  * The class demostrates the use of java.io.RandomAccessFile  */ public class WordList {     // This is a simple test method     public static void main(String args[  ]) throws IOException {         // Write command-line arguments to a WordList file named "words.data"         writeWords("words.data", args);                  // Now create a WordList based on that file         WordList list = new WordList("words.data");         // And iterate through the elements of the list backward         // This would be very inefficient with sequential-access streams         for(int i = list.size( )-1; i >= 0; i--)              System.out.println(list.get(i));         // Tell the list we're done with it.         list.close( );     }     // This static method creates a WordList file     public static void writeWords(String filename, String[  ] words)         throws IOException     {         // Open the file for read/write access ("rw").  We only need to write,         // but have to request read access as well         RandomAccessFile f = new RandomAccessFile(filename, "rw");         // This array will hold the positions of each word in the file         long wordPositions[  ] = new long[words.length];         // Reserve space at the start of the file for the wordPositions array         // and the length of that array. 4 bytes for length plus 8 bytes for         // each long value in the array.         f.seek(4L + (8 * words.length));         // Now, loop through the words and write them out to the file,         // recording the start position of each word.  Note that the         // text is written in the UTF-8 encoding, which uses 1, 2, or 3 bytes         // per character, so we can't assume that the string length equals         // the string size on the disk.  Also note that the writeUTF( ) method         // records the length of the string so it can be read by  readUTF( ).         for(int i = 0; i < words.length; i++) {             wordPositions[i] = f.getFilePointer( ); // record file position             f.writeUTF(words[i]);                  // write word         }         // Now go back to the beginning of the file and write the positions         f.seek(0L);                                   // Start at beginning         f.writeInt(wordPositions.length);             // Write array length         for(int i = 0; i < wordPositions.length; i++) // Loop through array             f.writeLong(wordPositions[i]);              // Write array element         f.close( );   // Close the file when done.     }     // These are the instance fields of the WordList class     RandomAccessFile f;  // the file to read words from     long[  ] positions;    // the index that gives the position of each word     // Create a WordList object based on the named file     public WordList(String filename) throws IOException {         // Open the random access file for read-only access         f = new RandomAccessFile(filename, "r");         // Now read the array of file positions from it         int numwords = f.readInt( );             // Read array length         positions = new long[numwords];         // Allocate array         for(int i = 0; i < numwords; i++)       // Read array contents             positions[i] = f.readLong( );     }     // Call this method when the WordList is no longer needed.     public void close( ) throws IOException {         if (f != null) f.close( );  // close file         f = null;                  // remember that it is closed         positions = null;     }     // Return the number of words in the WordList     public int size( ) {         // Make sure we haven't closed the file already         if (f == null) throw new IllegalStateException("already closed");         return positions.length;     }     // Return the string at the specified position in the WordList     // Throws IllegalStateException if already closed, and throws     // ArrayIndexOutOfBounds if i is negative or >= size( )     public String get(int i) throws IOException {         // Make sure close( ) hasn't already been called.         if (f == null) throw new IllegalStateException("already closed");         f.seek(positions[i]);  // Move to the word position in the file.         return f.readUTF( );    // Read and return the string at that position.     } }


Java Examples in a Nutshell
Java Examples in a Nutshell, 3rd Edition
ISBN: 0596006209
EAN: 2147483647
Year: 2003
Pages: 285

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net