Random-Access Files
So far, we have seen how to create and manipulate sequential-access files. Sequential-access files are inappropriate for so-called instant-access applications, in which the desired information must be located immediately. Some popular instant-access applications are airline-reservation systems, banking systems, point-of-sale systems, automated teller machines (ATMs) and other kinds of transaction-processing systems that require rapid access to specific data. The bank at which you have your account may have hundreds of thousands, or even millions, of other customers, but when you use an ATM, the bank determines in seconds whether your account has sufficient funds for the transaction. This kind of instant access is possible with random-access files and with databases (Chapter 25). A program can access individual records of a random-access file directly (and quickly) without searching through other records. Random-access files are sometimes called direct-access files.
Recall from Section 14.5 that Java does not impose structure on a file, so an application that wants to use random-access files must specify the format of those files. Several techniques can be used to create random-access files. Perhaps the simplest is to require that all the records in a file be of the same fixed length. Using fixed-length records makes it easy for a program to calculate (as a function of the record size and the record key) the exact location of any record relative to the beginning of the file. We soon see how this capability facilitates direct access to specific records, even in large files.
Figure 14.22 illustrates Java's view of a random-access file composed of fixed-length records. (Each record in this figure is 100 bytes long.) A random-access file is like a railroad train with many carssome empty, some with contents.
Figure 14.22. Java's view of a random-access file.
A program can insert data in a random-access file without destroying the other data in the file. Similarly, a program can update or delete data stored previously without rewriting the entire file. In the following sections, we explain how to create a random-access file, enter data, read the data both sequentially and randomly, update the data and delete the data.
14.7.1. Creating a Random-Access File
A RandomAccessFile is useful for direct-access applications. With a sequential-access file, each successive input/output request reads or writes the next consecutive set of data in the file. With a random-access file, each successive input/output request could be directed to any part of the fileperhaps a section widely separated from the part referenced in the previous request. Direct-access applications provide rapid access to specific data items in large files, but users often have to wait for answers. In many instances, however, answers must be made available quickly, to prevent people from becoming impatient and taking their business elsewhere.
RandomAccessFile objects have all the capabilities of classes FileInputStream and FileOutputStream, as well as the capabilities described by interfaces DataInput and DataOutput. These interfaces provide methods for reading and writing primitive-type values, byte arrays and strings. When a program associates an object of class RandomAccessFile with a file, the program reads or writes data, beginning at the location in the file specified by the file-position pointer (the byte number of the next byte in the file to be read or written to), and manipulates all the data as primitive types. When writing an int value, four bytes are output to the file. When reading a double value, eight bytes are input from the file. The size of the types is guaranteed, because Java has fixed representations and sizes for all primitive types, regardless of the computing platform.
Random-access file-processing programs rarely write a single field to a file. Normally they write one object at a time, as we show in the upcoming examples. Consider the following problem:
Create a transaction-processing program capable of storing up to 100 fixed-length records for a company that can have up to 100 customers. Each record should consist of an account number (that will be used as the record key), a last name, a first name and a balance. The program should be able to update an account, insert a new account and delete an account.
The next several sections introduce the techniques necessary to create this credit-processing program. Figure 14.23 contains the RandomAccessAccountRecord class that is used by the next four programs for both reading records from and writing records to a file. Class RandomAccessAccountRecord inherits our AccountRecord implementation (Fig. 14.6), which includes private fieldsaccount, lastName, firstName and balanceas well as set and get methods for each field. We could inherit from either AccountRecord or AccountRecordSerializable. We do not use object serialization when processing random-access files in this chapter, so we inherit from class AccountRecord. Note that the class is in package com.deitel.jhtp6.ch14.
Figure 14.23. RandomAccessAccountRecord class used in random-access file programs.
(This item is displayed on pages 708 - 709 in the print version)
1 // Fig. 14.23: RandomAccessAccountRecord.java 2 // Subclass of AccountRecord for random-access file programs. 3 package com.deitel.jhtp6.ch14; // packaged for reuse 4 5 import java.io.RandomAccessFile; 6 import java.io.IOException; 7 8 public class RandomAccessAccountRecord extends AccountRecord 9 { 10 public static final int SIZE = 72; 11 12 // no-argument constructor calls other constructor with default values 13 public RandomAccessAccountRecord() 14 { 15 this ( 0, "", "", 0.0 ); 16 } // end no-argument RandomAccessAccountRecord constructor 17 18 // initialize a RandomAccessAccountRecord 19 public RandomAccessAccountRecord( int account, String firstName, 20 String lastName, double balance ) 21 { 22 super( account, firstName, lastName, balance ); 23 } // end four-argument RandomAccessAccountRecord constructor 24 25 // read a record from specified RandomAccessFile 26 public void read( RandomAccessFile file ) throws IOException 27 { 28 setAccount( file.readInt() ); 29 setFirstName( readName( file ) ); 30 setLastName( readName( file ) ); 31 setBalance( file.readDouble() ); 32 } // end method read 33 34 // ensure that name is proper length 35 private String readName( RandomAccessFile file ) throws IOException 36 { 37 char name[] = new char[ 15 ], temp; 38 39 for ( int count = 0; count < name.length; count++ ) 40 { 41 temp = file.readChar(); 42 name[ count ] = temp; 43 } // end for 44 45 return new String( name ).replace( ' |