14.9. Reading from a Random-Access File Sequentially

In the previous sections, we created a random-access file and wrote data to that file. In this section, we develop a program that reads the file sequentially and prints only those records that contain data. These programs produce an additional benefit. See if you can determine what it is; we’ll reveal it at the end of this section.

The istream function read inputs a specified number of bytes from the current position in the specified stream into an object. For example, lines 31–32 from Fig. 14.13 read the number of bytes specified by sizeof(ClientData) from the file associated with ifstream object inCredit and store the data in the client record. Function read requires a first argument of type char *. Since &client is of type ClientData *, &client must be cast to char * using the cast operator reinterpret_cast.


 1   // Fig. 14.13: Fig14_13.cpp
 2   // Reading a random-access file sequentially.
 3   #include <iostream>
 4   #include <iomanip>
 5   #include <fstream>  
 6   #include <cstdlib>
 7   #include "ClientData.h" // ClientData class definition
 8   using namespace std;
 9
10   void outputLine( ostream&, const ClientData & ); // prototype
11
12   int main()
13   {
14      ifstream inCredit( "credit.dat", ios::in | ios::binary );
15
16      // exit program if ifstream cannot open file
17      if ( !inCredit )
18      {
19         cerr << "File could not be opened." << endl;
20         exit( EXIT_FAILURE );
21      } // end if
22
23      // output column heads
24      cout << left << setw( 10 ) << "Account" << setw( 16 )
25         << "Last Name" << setw( 11 ) << "First Name" << left
26         << setw( 10 ) << right << "Balance" << endl;
27
28      ClientData client; // create record
29
30      // read first record from file                       
31      inCredit.read( reinterpret_cast< char * >( &client ),
32         sizeof( ClientData ) );                           
33
34      // read all records from file
35      while ( inCredit && !inCredit.eof() )
36      {
37         // display record
38         if ( client.getAccountNumber() != 0 )
39            outputLine( cout, client );
40
41         // read next from file                               
42         inCredit.read( reinterpret_cast< char * >( &client ),
43            sizeof( ClientData ) );                           
44      } // end while
45   } // end main
46
47   // display single record
48   void outputLine( ostream &output, const ClientData &record )
49   {
50      output << left << setw( 10 ) << record.getAccountNumber()
51         << setw( 16 ) << record.getLastName()
52         << setw( 11 ) << record.getFirstName()
53         << setw( 10 ) << setprecision( 2 ) << right << fixed
54         << showpoint << record.getBalance() << endl;
55   } // end function outputLine


Account   Last Name       First Name    Balance
29        Brown           Nancy          -24.54
33        Dunn            Stacey         314.33
37        Barker          Doug             0.00
88        Smith           Dave           258.34
96        Stone           Sam             34.98


Fig. 14.13. Reading a random-access file sequentially.

Figure 14.13 reads every record in the credit.dat file sequentially, checks each record to determine whether it contains data, and displays formatted outputs for records containing data. The condition in line 35 uses the ios member function eof to determine when the end of file is reached and causes execution of the while statement to terminate. Also, if an error occurs when reading from the file, the loop terminates, because inCredit evaluates to false. The data input from the file is output by function outputLine (lines 48–55), which takes two arguments—an ostream object and a clientData structure to be output. The ostream parameter type is interesting, because any ostream object (such as cout) or any object of a derived class of ostream (such as an object of type ofstream) can be supplied as the argument. This means that the same function can be used, for example, to perform output to the standard-output stream and to a file stream without writing separate functions.

What about that additional benefit we promised? If you examine the output window, you’ll notice that the records are listed in sorted order (by account number). This is a consequence of how we stored these records in the file, using direct-access techniques. Sorting using direct-access techniques is relatively fast. The speed is achieved by making the file large enough to hold every possible record that might be created. This, of course, means that the file could be occupied sparsely most of the time, resulting in a waste of storage. This is an example of the space-time trade-off: By using large amounts of space, we can develop a much faster sorting algorithm. Fortunately, the continuous reduction in price of storage units has made this less of an issue.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.244.83