Iostream support for file positioning operations depends on the character encoding of a particular stream. For fixed-width encodings, such as ASCII or UNICODE, the file stream classes allow a full set of positioning operations comparable to those offered by `C' stdio. The options for variable-width and state-dependent encodings, such as JIS, are much more limited. For these more complex encodings, the only allowed positioning operations are 'seek to beginning', 'seek to end', or 'seek to a previously known location'. The last option requires that you arrive at and then store a particular position before a seek can be performed. Attempting to seek to an arbitrary offset on a stream with variable-width or state-dependent character encodings has no effect on the file position. Here's an example of the correct way to seek to a position in any file stream, regardless of encoding:
int main(int argc, char argv[]) { ofstream fs("foo.out"); fs << "Anyone"; //1 ofstream::pos_type p = fs.tellp(); //2 fs << " remember J.P. Patches?"; //3 fs.seekp(p); //4 return 0; }
//1 | Here we output some characters in order to move the file position to some arbitrary location that we'll later seek back to. |
//2 | Now we use the tellp() function to save the current file position. |
//3 | Output some more text to move the file position along. |
//4 | Finally, seek back to our previously saved position. |
This is the only possible method for seeking to an arbitrary position--that is, a position other than beginning or end of file--in a stream with variable or state-dependent character encoding. Of course, the method also works with fixed-width encodings.
The example above shows one use of two of the output file positioning functions, tellp and a version of seekp. An ofstream also has another version of the seekp function that allows a seek to an arbitrary offset in much the same way that the `C' stdio fseek function works. This function can be used to seek to the beginning or end of any ofstream, or anywhere else in an ofstream with a fixed-width character encoding. For instance:
ofstream fs("foo.out"); fs << "Anyone remember J.P. Patches?"; fs.seekp(-2,ios_base::cur); //1 fs.seekp(0,ios_base::beg); //2
//1 | Seek back two characters. Position at the s in Patches. |
//2 | Seek to beginning of the file. |
The first parameter of this function is an ofstream::off_type, and the second is one of three constants indicating starting position for the seek. These three values correspond to the three possible seek types available with the `C' stdio function fseek. They are defined in the base class ios_base. The table below summarizes the three different kinds of seeks possible with this version of seekp:
Type of seek | Argument to seekp | `C' stdio equivalent |
seek from beginning of file |
ios_base::beg |
SEEK_SET |
seek from end of file |
ios_base::end |
SEEK_END |
seek from current position |
ios_base::cur |
SEEK_CUR |
As in the example, passing 0 as the offset with ios_base::beg as the seek type seeks to the beginning of the file. Likewise, using 0 with ios_base::end seeks to the end of the file. Since the function returns the current position after the seek operation, passing 0 along with ios_base::cur gets you the current file position without moving it. This is equivalent to calling the tellp() function.
The ifstream class provides the same set of functions but with slightly different names: tellg() instead of tellp(), and seekg(...) instead of seekp(...). The reason for this specialized naming scheme can be seen in the fstream class, which provides both sets of functions so that the input and output streams can be manipulated separately.
If you look at the iostream class definitions, you notice that the seek functions are not defined in these classes. Instead, they are obtained from a base class: basic_ostream for tellp and seekp, and basic_istream for tellg and seekg. These functions then call virtual functions in the stream buffer, where seeking is actually implemented. Seek functions for ofstream, ifstream, and fstream actually call seekoff and seekpos in filebuf. The code looks like this:
basic_ofstream basic_ostream::seekp(pos) ->basic_streambuf::pubseekpos(pos) ->(virtual) basic_filebuf::seekpos(pos)
Calling virtual functions in the stream buffer maintains the fundamental separation of buffer manipulation and I/O from string formatting. While it's not necessary to know this in order to use file seek operations, it is important if you ever need to subclass a stream buffer.
OEM Edition, OEM Edition, ©Copyright 1999, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.