home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


Seeking Strategies

Using the seek function is usually only useful when dealing with binary streams. It is most commonly used for database or database-like operations in which records are fetched from a data file. To get to a certain record stored in a binary file, the location of the record must be calculated. This calculation is usually a multiple of the record size; for example, sizeof(myRecord)*2 would be the start position of the third record in the file. The following function (from file.cpp) demonstrates random record access for the data file:

void PhoneDatabase::GetRecord( PhoneRecord& record, int recnum )
{
   if( recnum != current )
    {
       Datafile.seekg( (recnum * sizeof(PhoneRecord)) ) ;
	CurrentRecord = ++recnum ;
   }
   else
       CurrentRecord++ ;

   Datafile.read( (char*) &record, sizeof(PhoneRecord)) ;
}

What’s the best way to work with data in files? It depends on the data. It is possible to abstract this any number of ways. For some kinds of data, it’s possible to overload the array index operator[] to implement random access. This can be implemented either by accessing a function like the preceding code (to keep the code that actually fetches things in one place for easy maintainability), or by directly accessing the file stream object. For sequential access, your database file management class can be given a stream-like interface, but records can be streamed instead of streaming fundamental data types.

Using overloading, it’s possible to stream objects out of a database and to an output stream using code that looks very familiar:

cout << rec << endl ;

   while( db >> rec )
   {
      cout << rec << endl ;
   }

This technique is useful any time anything sequential needs to be done. This does not necessary reflect that the underlying data has to be sequential. For instance, a SQL query class might allow the returned result records to be accessed sequentially using this method.

Steps

Using the ability to seek in a stream is very data dependent. The details of these techniques are used in the sample phonebook program, sample.cpp. Using the ability to seek should never be added to an existing program because it’s so fundamental to the way data is handled.

1.  Seek functions see the data file as an array of bytes, and it’s up to your program to determine from what point to start interpreting data. Usually, it will be some multiple of the size of the data type in the file, or some offset (for any leading information) plus some multiple of the record stored.
2.  Seek functions for reading use the seekg member function, as demonstrated in the following code:
void PhoneDatabase::GetRecord( PhoneRecord& record, int recnum )
{
   if( recnum != current )
   {
      Datafile.seekg( (recnum * sizeof(PhoneRecord)) ) ;
      CurrentRecord = ++recnum ;
   }
   else
      CurrentRecord++ ;

   Datafile.read( (char*) &record, sizeof(PhoneRecord)) ;
}
3.  When seeking to write to a location to a file, use the seekp member function, as shown in the following:
void PhoneDatabase::UpdateRecord( const PhoneRecord& record,
				          ⇒ int recnum )
{
   if( recnum != current )
   {
	Datafile.seekp( (recnum * sizeof(PhoneRecord)) ) ;
	 CurrentRecord = recnum++ ;
   }
   else
     CurrentRecord++ ;

   Datafile.write( (char*) &record, sizeof(PhoneRecord)) ;
}
4.  Seeking from the current position accepts both positive and negative values, the following code demonstrates using tellp() and a relative seekp() function.
void PhoneDatabase::AddRecord( const PhoneRecord& record )
{
    Datafile.seekp( 0, ios::end ) ;
   CurrentRecord = Datafile.tellp() / sizeof(PhoneRecord) + 1 ;
   Datafile.write( (char*) &record, sizeof(PhoneRecord) ) ;
}

The technique for finding the current record index based on the file position is also shown in the preceding code.

How It Works

As mentioned earlier, seek methods view a binary data file as an array of bytes. This gives the programmer the freedom to implement any required sort of structure in the disk file. Some file formats become quite elaborate. Complexity is the flip side of the cointhe more complex the file format, the more complex the code to read data from the file, and the greater the chance of a programming error.

Comments

When working with binary files, and especially when designing your own file format, simplicity is the goal to keep in mind. Many subtle errors can be introduced into a program when code that works with binary data miscalculates the offset in the file it is to read from. Another thing to keep in mind is that most binary data, such as floating-point numbers and integers, is not human-readable in binary form, which makes debugging of subtle file format errors even more difficult.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.