In a program that receives input from an fstream object (a file), you can associate the fstream object with a filebuf object, and then use the filebuf object to move the get or put pointer forward or backward in the file. You can also use filebuf member functions to determine the length of the file.
To associate an fstream object with a filebuf object, you must first construct the fstream object and open it. You then use the rdbuf() member function of the fstream class to obtain the address of the file's filebuf object. Using this filebuf object, you can move through the file or determine the file's length, with the seekpos() and seekoff() functions. For example:
// Using the filebuf class to move through a file
#include <fstream.h> // for use of fstream classes #include <iostream.h> // not really needed since fstream includes it #include <stdlib.h> // for use of exit() function
void main() {
// declare a streampos object to keep track of the position in filebuf
streampos Position;
// declare a streamoff object to set stream offsets // (for use by seekoff and seekpos) streamoff Offset=0;
// declare an fstream object and open its file for input
fstream InputFile("algonq.uin",ios::in);
// check that input was successful, exit if not
if (!InputFile) {
cerr << "Could not open algonq.uin! Exiting...\n";
exit(-1);
}
// associate the fstream object with a filebuf pointer filebuf *InputBuffer=InputFile.rdbuf();
// read the first line, and display it char LineOfFile[128]; InputFile.getline(LineOfFile,sizeof(LineOfFile),'\n'); cout << LineOfFile << endl;
// Now skip forward 100 bytes and display another line
Offset=100;
Position=InputBuffer->seekoff(Offset,ios::cur,ios::in);
InputFile.getline(LineOfFile,sizeof(LineOfFile),'\n');
cout << "At position " << Position << ":\n"
<< LineOfFile << endl;
// Now skip back 50 bytes and display another line
Offset=-50;
Position=InputBuffer->seekoff(Offset,ios::cur,ios::in);
// ios::cur refers to current position in buffer
InputFile.getline(LineOfFile,sizeof(LineOfFile),'\n');
cout << "At position " << Position << ":\n"
<< LineOfFile << endl;
// Now go to position 137 and display to the end of its line
Position=137;
InputBuffer->seekpos(Position,ios::in);
InputFile.getline(LineOfFile,sizeof(LineOfFile),'\n');
cout << "At position " << Position << ":\n"
<< LineOfFile << endl;
// Now close the file and end the program InputFile.close(); }
If the file algonq.uin contains the following text:
The trip begins on Round Lake. We proceed through a marshy portage, and soon find ourselves in a river whose water is the color of ink.
A heron flies off in the distance. Frogs croak cautiously alongside the canoes. We can feel the sun's heat glaring at us from grassy shores.
the output of the example program is:
The trip begins on Round Lake. At position 131: ink. At position 86: elves in a river whose water is the color of ink. At position 137: A heron flies off in the distance.
The following example shows how you can use both encoded and relative byte offsets to move through a file. Note that encoded offsets are specific to OS/390 C/C++ and programs that use them may not be portable to other VisualAge C++ (formerly C Set++) compilers.
// Example of using encoded and relative byte offsets // in seeking through a file
#include <iomanip.h> #include <fstream.h>
void main() {
fstream fs("tseek.data", ios::out); // create tseek.data
filebuf* fb = fs.rdbuf();
streamoff off[5];
int pos[5] = {0, 30, 42, 197, 0};
for (int i = 0, j = 0; i < 200; ++i) {
if (i == pos[j])
off[j++] = (*fb).seekoff(0L, ios::cur, ios::out);
fs << setw(4) << i;
if (i % 13 == 0 || i % 17 == 0) fs << endl;
}
fs.close();
cout << "Open the file in text mode, reposition using encoded\n"
<< "offsets obtained from previous calls to seekoff()" << endl;
fs.open("tseek.data", ios::in);
fb = fs.rdbuf();
// Exchange off[2] and off[3] so last seek will be backwards off[4] = off[2]; off[2] = off[3]; off[3] = off[4]; pos[4] = pos[2]; pos[2] = pos[3]; pos[3] = pos[4];
for (j = 0; j < 4; ++j) {
(*fb).seekoff(off[j], ios::beg, ios::in);
fs >> i;
cout << "data at pos" << dec << setfill(' ') << setw(4) << pos[j]
<< " is \"" << setw(4) << i << "\" (encoded offset was 0x"
<< hex << setfill('0') << setw(8) << off[h] << ")" << endl;
if (i != pos[j]) return 37 + 10*j;
}
fs.close();
cout.fill(' ');
cout.setf(ios::dec, ios::basefield);
cout << "\nOpen the file in binary byteseek mode, reposition using\n"
<< "byte offsets calculated by the user program" << endl;
fs.open("tseek.data", "byteseek", ios::in|ios::binary);
fb = fs.rdbuf();
for (j = 0, j < 4; ++j) {
off[j] = (*fb).seekoff(4*pos[j], ios::beg, ios::in);
fs >> i;
cout << "data at pos" << setw(4) << pos[j] << "is \"" << setw(4) << i
<< "\" (byte offset was " << setw(10) << off[j] << ")" << endl;
if (i != pos[j]) return 77 + 10*j;
}
}