How can I read a text file in reverse order (i.e. from eof) using C++?
Asked
Active
Viewed 6,052 times
0
-
@ControlAltDel: that's patent nonsense. You can read the file in chunks, backwards, so you don't have to read a whole file. While OSes usually only support reading forward, they also usually support seeking. (Otherwise, `tail` would be grossly inefficient) – nneonneo Sep 10 '14 at 19:35
-
Similar way you read it forward. You read buffers full of data from back of the file towards the front and present those buffers to the API backwards. Unfortunately there are no standard library classes that do it for you, like there are for forward reading files. – Galik Sep 10 '14 at 19:37
-
There are probably a dozen answers to this question already. Try the link or search... – Mats Petersson Sep 10 '14 at 19:46
3 Answers
3
Yes, but you basically have to do it manually.
The basic algorithm is as follows:
- Seek to the end of the file with
is.seekg(0, is.end)
- Determine the file size with
is.tellg()
- Repeatedly seek backwards and read chunks of the file until you reach the front

nneonneo
- 171,345
- 36
- 312
- 383
-
3.5. Scan the chunks for line endings if you want the lines in reverse order but the characters of each line in forward order. – Mark Ransom Sep 10 '14 at 19:34
1
If the file is small enough so the entire contents easily fit within memory, it will be both far faster and far easier to code to read the file forward into a string and then reversing that string after the fact.
If the contents won't fit in memory, you'll have to use nneonneo's solution. It would probably be best to turn off buffering.

David Hammen
- 32,454
- 9
- 60
- 108
0
Just use the seekg and related functions in istream class. Here is a working example. Tested.
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream in("file.txt");
// Get the length of the file
in.seekg(0, in.end);
int len = in.tellg();
// Start reading the file in reverse
char c;
while (len--)
{
in.seekg(len, in.beg);
in >> c;
cout << c;
}
}

jax
- 728
- 1
- 11
- 31
-
...though I wouldn't actually read the characters one-at-a-time because that is liable to be *extremely* slow. – nneonneo Sep 10 '14 at 19:53
-
-
2Reading characters one-at-a-time is always going to be slow. If you are unlucky and the implementation doesn't buffer the characters, then you are basically asking for a disk operation for every single character. Even with buffering, you have the overhead of a full function call and buffer handling logic, on every character. – nneonneo Sep 10 '14 at 20:03
-
-
2Instead of backing up one character at a time, back up, say, 4096 characters at a time, read 4096 characters, and reverse that buffer. Read from the buffer until the buffer runs out, then back up and read another buffer. – nneonneo Sep 10 '14 at 20:14
-
Okay. Would I use istream::read to read in chunks? What is the mechanism that decides weather a file reads from disk or not? I mean, if I call read wouldn't that also read one at a time internally, or am I wrong about this? – jax Sep 10 '14 at 20:20
-
2(1) yes, and (2) you don't actually know, because this is dependent on how the file read is implemented in your C++ library and in your kernel. – nneonneo Sep 10 '14 at 20:21
-
-
2because by doing the reads yourself, you skip a few intermediate function calls (on every single character), and you avoid having problems if the implementation doesn't buffer. – nneonneo Sep 10 '14 at 20:56
-
-
1Yes! But instead of doing the reads character-by-character you'd be doing the reads block-by-block, and then extracting characters from your buffer. – nneonneo Sep 10 '14 at 21:02