Understanding random or direct file access relies on concepts introduced previously. Please review the following as needed:
The current chapter began with two figures. The first suggests that a file looks like an array of bytes with a position pointer indicating where the program is currently reading or writing data. The second illustrates the primary C++ input/output system classes. Significantly, the iostream
class has two superclasses,
istream
and ostream
, and inherits a position pointer from each. So, fstream
, a subclass of iostream
, has two position pointers, one for input and one for output.
When it is important to do so, we distinguish the two pointers as "get" (read or input) and "put" (write or output). In preparation for accessing a specific data item, the program moves the pointers within a file with one of four overloaded "seek" functions. The next I/O operation occurs at the new position in the file. Additionally, two "tell" functions report a stream's current position within a file. The name of each function ends with either a "p" or a "g" to denote a specific pointer.
Function | Description |
---|---|
istream& seekg(streampos pos); |
Moves the "get" or "put" stream position to an absolute location, pos, in the file. Absolute positions are measured in bytes from the beginning of the file, pos must be ≥ 0. |
ostream& seekp(streampos pos); |
|
istream& seekg(streampos off, ios::seekdir loc); |
Moves the "get" or "put" stream position to a location relative to one of three file locations. The offset, off, is the number of bytes added to or subtracted from the specified location, loc, as denoted by one of the symbolic constants:
|
ostream& seekp(streampos off, ios::seekdir loc); |
|
streampos tellg(); |
Returns the current position of one of the position pointers within the file. The returned position is measured in bytes from the beginning of the file. Both functions return -1 on failure. |
streampos tellp(); |
read
or write
functions repeatedly, resulting a sequential access. However, switching between reading and writing requires an intervening "seek" function call:
In the Block I/O section, we learned that we can group the bytes together to form blocks or records, and that we can read and write block-oriented files sequentially. We can implement direct access by combining block I/O, the file positioning functions, and records. The previous discussion specified the seek positions in bytes. But a file of records looks and behaves very much like an array of objects. If we index into an array of objects, the compiler automatically converts the array index into a byte address in memory. To implement direct access, we need a way to map a record number (aka block number), the analog of an array index, to a byte address within the file. Unfortunately, C++ doesn't have a way to complete the mapping automatically, so we must do it manually.
struct chunk { . . . }; chunk c; fstream data; |
Specification and definitions for the examples |
data.seekp(0, ios::end); data.write((char *) &c, sizeof(chunk)); |
Write a new record at the end of the file |
data.seekg(0); data.read((char *) &c, sizeof(chunk)); |
Rewind to the beginning of the file and read the first record. |
data.seekg(0); while (data.read((char *) &c, sizeof(chunk))) .... |
Rewind to the beginning of the file and read all records in sequence |
data.seekp(data.tellg() - (streampos)sizeof(chunk)); data.write((char *) &c, sizeof(chunk)); |
Searching and replacing - seek to the position after the last read, back up one record, and overwrite the record that's already there |
data.seekp(ios::cur, -(streampos)sizeof(chunk)); data.write((char *) &c, sizeof(chunk)); |
Replace or overwrite the last record written |
data.seekp(0, ios::end); // (a) streampos pos = data.getp(); data.write((char *) &c, sizeof(chunk)); . . . data.seekg(pos); // (b) data.read((char *) &c, sizeof(chunk)); . . . data.seekp(pos); // (c) data.write((char *) &c, sizeof(chunk)); |
Simple database operations. Groups of code are separated by time. The variable pos may be a field in another object.
|