### Using filebuf Functions to Move Through a File

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.

### Using Encoded and Relative Byte Offsets to Move Through a File

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;
        }
    }