Paul_Justin
Paul_Justin

Reputation: 13

Access last 6 lines in a text file c++

I want to access the last 6 lines in a text file using c++. Can anyone provide me with a code that reaches there in a constant time? Thanks in advance. :)

fstream myfile("test.txt");
myfile.seekg(-6,ios_base::end);
string line;
while(getline(myfile,line))
{
    if(vect.size() != VSIZE)
    {
        vect.push_back(line);
    }
    else
    {
        vect.erase(v.begin());
        vect.push_back(line);
    }
}

It seems not to be working... and VSIZE is 6... please provide me with help and working code.

Upvotes: 1

Views: 92

Answers (4)

Probably the easiest approach is to just mmap() the file. This puts its contents into your virtual address space, so you can easily scan it from the end for the first six line endings.

Since mmapping a file gives you the illusion of the entire file being in memory in a single large buffer without actually loading the parts that you don't need, it both avoids unnecessary I/O and alleviates you from managing a growing buffer as you search backwards for the line endings.

Upvotes: 0

david.pfx
david.pfx

Reputation: 10863

This is quite a hard thing to do, and there are several edge cases to consider.

Broadly the strategy is:

  1. Open the file in binary mode so you see every byte.
  2. Seek to (end - N), where N is the size of an arbitrary buffer. About 1K should do it.
  3. Read N bytes into a buffer. Scan backwards looking for LF characters ('\n). Skip the one at the end, if there is one.
  4. Each line starts just after an LF, so count the lines backwards until you get to 6.
  5. If you don't find 6 then seek backwards another N bytes, read another buffer and continue the scan.
  6. If you reach the beginning of the file, stop.

I leave the code as an exercise.

Upvotes: 0

bobah
bobah

Reputation: 18864

This answer explains why what you do won't work. Below I explain what will work.

  1. Open the file in the binary mode.
  2. Read forward from the start storing positions of '\n' in a circular buffer of length 6. (boost::circular_buffer can help)
  3. Dump the contents of the file starting from the smallest position in the ring buffer.

Step 2 can be improved by seeking to end-X where X is derived by some sort of bisection around the end of file.

Upvotes: 0

perreal
perreal

Reputation: 98118

This line:

myfile.seekg(-6,ios_base::end);

seeks to the 6th byte before the end of the file, not 6 lines. You need to count the newline backwards or start from the beginning. So your code should work if you remove the line above.

Upvotes: 2

Related Questions