0

I need to find a way of reading in the last 6 lines of data from a file.

For example if I have 1 2 3 4 5 6 7 8 9 10

I need to read be able to get 10, 9, 8, 7, 6, 5, 4.

These need to then be put into variables or strings to be outputted later. Currently I have managed to read in the last line of the file but I have no idea how to then read in the other 5 numbers.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std; 

int main()
{
    std::ifstream in("test.txt");

    if (in.is_open())
    {
        std::vector<std::string> lines_in_reverse;

        std::string line, line2;

        while (std::getline(in, line))
        {
            // Store the lines in reverse order.
            lines_in_reverse.insert(lines_in_reverse.begin(), line);



        }
        cout << line << endl;
        while (std::getline(in, line2))
        {
            // Store the lines in reverse order.
            lines_in_reverse.insert(lines_in_reverse.begin(), line2);



        }
        cout << line2 << endl;
    }

    cin.get();
    return 0;
}

Can anyone advise a way to this? I do not know of any functions or methods that can help.

EDIT

This method outputs the last 6 numbers from the file however they are backwards and I need a way to reverse them and get rid of the whitespace it prints out.

I'm unsure on how to use reverse and which arguments are required from this - http://en.cppreference.com/w/cpp/algorithm/reverse

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
    char x;
    ifstream f("test.txt", ios::ate);
    streampos size = f.tellg();
    for (int var = 1; var <= size; var++){
        f.seekg(-var, ios::end);
        f.get(x);
        reverse(x);
        cout << x; 
    }
    cin.get();
    return 0;
}

Alot of the responses show me how to reverse the text file using vectors but not the last 6 numbers which is the only information I need.

Regards

PapaSmurf
  • 161
  • 4
  • 15
  • Read the lines in order, and add them to the vector in order, the *print* them in reverse order. Remember that you can iterate over a vector both from the beginning to the end, as well as from the end to the beginning. – Some programmer dude Jan 03 '15 at 07:24
  • @JoachimPileborg That works, but I too am wondering if there is a more direct way to do this using the fstream library. I know one way is to directly manipulate the file pointer, but that is not very elegant. Consider when you have a large file (several gigs). It would be a complete waste of memory to store the whole file. – 1110101001 Jan 03 '15 at 07:30
  • I'll give this a go and post whether it works thanks – PapaSmurf Jan 03 '15 at 07:35
  • Also, if you need to use the reversed vector other than just printing it, then [it's very easy to reverse it](http://en.cppreference.com/w/cpp/algorithm/reverse). – Some programmer dude Jan 03 '15 at 07:54
  • @1110101001 You can't reliably read text files in reverse in a simple way. Then you have to read character by character, handling newlines, and appending to strings and append to the collection. Reading it from the beginning, reversing the vector and printing the vector is four lines of C++ code (not including declarations). – Some programmer dude Jan 03 '15 at 07:55
  • If I was to print them in reverse order how would I get it to stop printing after the 6th number? – PapaSmurf Jan 03 '15 at 08:22

3 Answers3

2

It's not a good idea to store all the lines you read in, because there can be e.g. a billion lines.

You only need to store the last 6.

The following code is designed to produce those lines in reverse order, as the question indicates that is a requirement:

#include <iostream>
#include <string>
#include <deque>
using namespace std;

auto main() -> int
{
    string          line;
    deque<string>   last_lines;
    while( getline( cin, line ) )
    {
        if( last_lines.size() == 6 )
        {
            last_lines.pop_back();
        }
        last_lines.push_front( line );
    }

    for( auto const& s : last_lines )
    {
        cout << s << endl;
    }
}

The output here is not exactly the question's example

10, 9, 8, 7, 6, 5, 4

because that's 7 lines, contradicting the 6 that's stated in the first sentence.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
2

How to read a file and print it reverse, in only three statements of code (excluding declarations and other boilerplate):

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

void read_and_print_reverse_n(std::istream& is, const int n)
{
    std::vector<std::string> v;

    // This call reads all whitespace-delimited "words" from the input stream
    // and appends them to the vector
    std::copy(std::istream_iterator<std::string>(is),
              std::istream_iterator<std::string>(),
              std::back_inserter(v));

    // Output the last `n` lines from the input
    for (const auto i = v.rbegin();
         i < v.rend() && i < v.rbegin() + n;
         ++i)
    {
        std::cout << *i << '\n';
    }
}

int main()
{
    read_and_print_reverse_n(std::cin, 6);
}

References

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I don't understand this about two lines. It's not a big deal to format that code into a single line. Also, I think this should be a comment, not an answer. – Cheers and hth. - Alf Jan 03 '15 at 10:27
  • @Cheersandhth.-Alf Maybe I should have said "two statements" instead? And for what the OP wants this is basically the shortest and simplest solution possible. It does all the OP wants with just those two statements, and it's "C++-ish" as it can be. – Some programmer dude Jan 03 '15 at 11:40
  • Maybe you just read the title and not the first line, "I need to find a way of reading in the last 6 lines of data from a file". As it is this answer is just a comment about how to do one support thing. – Cheers and hth. - Alf Jan 03 '15 at 13:25
  • @PapaSmurf Updated answer with a "normal" `for` loop to print only `n` lines, where `n` can be any number you want. – Some programmer dude Jan 04 '15 at 02:03
1

I think the answer here would solve the purpose where you store the lines in a vector and iterate the vector from the end.

As you are looking for some direct method to read the file, you can read the file character by character starting from the end using seekg and tellg.

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    using namespace std;
    int main()
    {
        char x;
        ifstream f("filename.txt",ios::ate);
        streampos size = f.tellg();
        for(int var=1;var<=size;var++){
            f.seekg(-var,ios::end);
            f.get(x);
            printf("%c",x);
        }
        return 0;
    }

You can also keep a count of \n to keep a track of the number of lines read from the end.

Community
  • 1
  • 1
richik jaiswal
  • 1,902
  • 1
  • 17
  • 21
  • This reads the numbers out backwards if they are more than one digit though. It there a way around this? – PapaSmurf Jan 03 '15 at 08:08
  • @PapaSmurf As the characters are printed in a reverse fashion, you can store the string and print its reverse using the reverse function in the algorithm library in c++. The main advantage of the method I stated is it saves you from reading the entire file and reads only the desired lines beginning from the last unlike vectors. – richik jaiswal Jan 03 '15 at 08:31
  • @Richik_Jaiswal Hi, please see updated with queries on using the reverse function and dealing with whitespace. – PapaSmurf Jan 03 '15 at 14:49
  • `int main() { char x; string s; ifstream f("test.txt",ios::ate); streampos size = f.tellg(); for(int var=1;var<=size;var++){ f.seekg(-var,ios::end); f.get(x); if(x!='\n') { s+=x; } if(x=='\n' || var==size) { cout<<"\n"; reverse(s.begin(),s.end()); cout< – richik jaiswal Jan 03 '15 at 19:12