Position inside streams

Location
  1. Courses

    /

  2. Complete C++ Course

    /

  3. The C++ Standard Library

    /

  4. Streams

    /

  5. Position inside streams

The cursor of stream objects

In this page, we will see how to retrieve and change the position of the cursor inside a stream object. Input stream and output stream objects both have their own cursor, so streams that can both input and output (std::iostream) have two internal cursors.

Setting the position inside an output stream

The method overloads to change the cursor inside an output stream are std::ostream& std::ostream::seekp(std::streampos pos) and std::ostream& std::ostream::seekp(std::streamoff off, std::ios::seekdir from). The first overload sets the cursor of the stream object with the position specified as argument, in bytes, relatively to the start of it. The second one sets the cursor to the position given as first argument, relatively to the location given as second argument.

The class streampos, taken as argument in the method overloads from above, represents a position inside a stream and can be automatically assigned with / converted to an integer number.

1
2
std::streampos pos = 12; int pos2 = pos;

The second argument may receive one of the following values:

ValueMeaning
std::ios::begRelatively to the beginning of the file.
std::ios::curRelatively to the current position of the cursor.
std::ios::endRelatively to the end of the file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <fstream> int main() { char bytes[] = {111, 97, 64, 32}; std::ofstream file("file.bin", std::ios::binary); /* Sets the cursor of the stream at the position 4 (In bytes), from the start of it. When the cursor is at the position 4, that basically means there are 4 bytes behind it. */ file.seekp(4); /* Writes 4 four bytes at the position 4 inside the file. */ file.write(bytes, 4); /* If we consider asterisks as unknown values, the bytes at the start of the file should be: (*) (*) (*) (*) (111) (97) (64) (32) */ /* Sets the cursor of the stream at the position 4, relatively to the current position. */ file.seekp(4, std::ios::cur); /* Writes 4 four bytes inside the file. */ file.write(bytes, 4); /* If we consider asterisks as unknown values, the bytes at the start of the file should be: (*) (*) (*) (*) (111) (97) (64) (32) (*) (*) (*) (*) (111) (97) (64) (32) */ return 0; }

Retrieving the position inside an output stream

The method std::streampos std::ostream::tellp() returns the global position (Position relatively to the beginning of the stream) of the cursor inside the output stream it is called from.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <fstream> #include <iostream> int main() { std::ofstream file("file.txt"); std::cout << "The position inside the stream starts at " << file.tellp() << '.' << std::endl; /* "The position inside the stream starts at 0." is printed into the console. */ file << "I am a string."; std::cout << "The stream cursor is now at position " << file.tellp() << '.' << std::endl; /* " The stream cursor is now at position 14." is printed into the console. */ return 0; }

Without much surprise, output operations on a stream object changes the position of its cursor.

Setting the position inside an input stream

Methods used to set and retrieve the position of the cursor inside an input stream object are the same as the ones from an output stream, except that the name of the methods end with the letter 'g' instead of 'p'. The reason they are named differently is to differentiate, with stream objects that handle both input and output (std::iostream), between the methods that work with the input cursor and those who work with the output cursor.

So, the overloads of the method to set the cursor inside an input stream are std::istream& std::istream::seekg(std::streampos pos) and std::istream& std::istream::seekg(std::streamoff pos, std::ios::seekdir from). The arguments are the same as with the equivalent overloads from output streams.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <fstream> int main() { std::ifstream file("file.bin",std::ios::binary); char bytes[4]; // If the file exists. if(file.is_open()) { // Sets the cursor at 4 bytes before the end of the stream. file.seekg(-4, std::ios::end); // Reads the 4 last bytes of the stream. file.read(bytes, 4); } return 0; }

Retrieving the position inside an input stream

The method std::streampos std::istream::tellg() returns the position of the cursor from the input stream it is called from.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <fstream> #include <iostream> int main() { std::ifstream file("file.txt"); // If the file exist if(file.is_open()) { std::cout << "Position of the cursor: " << file.tellg() << ".\n"; std::string word; // Reads a word from the stream. file >> word; std::cout << "Word read: \"" << word << "\".\n"; std::cout << "Position of the cursor: " << file.tellg() << ".\n"; } return 0; }

Retrieving the size of a stream

To retrieve the size of a stream, we can simply set the cursor to the end of the stream and then retrieve its position. Since the position of the cursor represents the number of bytes behind it, if it is at the end of the stream, its value is the size (In bytes) of the source linked to the stream (Example, a file).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <fstream> #include <iostream> int main() { std::fstream file("file.txt", std::ios::in); // If the file exists. if(file.is_open()) { // Sets the cursor at the end of the stream object. file.seekg(0, std::ios::end); // Prints the size of the file. std::cout << "Size of the file: " << file.tellg() << ".\n"; } return 0; }