A better way to tail a file

Discussion in 'C++' started by Count Dracula, Aug 9, 2003.

  1. Is there a way to write a c++ program that will
    print out the last few lines of a file without reading
    the whole file? The implementations of 'tail' I have
    seen all appear to be system dependent. I am looking for
    a standard (portable) c++ solution that will do just a
    fraction of tail's functionality. To make a long story short,
    I am looking for suggestions that may help me improve the
    speed of the following implementation for long input files:

    /*
    Command line utility to display the last few lines of a text file.

    Usage: (1) tail <filename>
    (2) tail <filename> <number of lines>

    <filename> is the name of the file whose last few lines you want to
    display
    <number of lines> is the number of lines you want to display
    (default is NumberOfLines)

    Implementation note: this is an inefficient implementation that
    reads the whole file
    only to display a few lines from the end of the file.
    */

    #include <string>
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <deque>

    // Forward declarations
    bool writetail(const std::string & filename, long numlines);
    void usage(long NumberOfLines);

    int main (int argc, char** argv)
    {
    const long NumberOfLines = 10;
    long numlines;
    std::string filename;
    switch (argc)
    {
    case 2:
    filename = argv[1];
    numlines = NumberOfLines;
    break;
    case 3:
    filename = argv[1];
    numlines = strtol(argv[2], NULL, 10);
    if (numlines <= 0 || errno == ERANGE)
    {
    std::cerr << argv[0] << ": error in second command line
    argument" << '\n';
    usage(NumberOfLines);
    return 1;
    }
    break;
    default:
    std::cerr << argv[0] << ": missing command line arguments" <<
    '\n';
    usage(NumberOfLines);
    return 1;
    }
    bool status = writetail(filename, numlines);
    if (!status)
    {
    std::cerr << argv[0] << ": execution errors" << '\n';
    usage(NumberOfLines);
    return 1;
    }
    return 0;
    }

    bool writetail(const std::string & filename, long numlines)
    {
    std::ifstream input(filename.c_str());
    if (!input)
    {
    std::cerr << "writehead: error opening file: " << filename <<
    '\n';
    return false;
    }
    std::string s;
    std::deque<std::string> lines;
    long kount = 0;
    while (std::getline(input, s))
    {
    lines.push_back(s);
    ++kount;
    if (kount == numlines) break;
    }
    while (std::getline(input, s))
    {
    lines.pop_front();
    lines.push_back(s);
    }
    std::deque<std::string>::iterator p;
    for (p = lines.begin(); p < lines.end(); ++p)
    std::cout << *p << '\n';
    input.close();
    return true;
    }

    void usage(long NumberOfLines)
    {
    std::cerr << "usage: tail <filename> <number of lines (optional)>\n"
    <<
    " <filename> is the name of the file whose last
    few lines you want to display\n" <<
    " <number of lines> is the number of lines you
    want to display (default is " <<
    NumberOfLines << ")\n";
    }
    Count Dracula, Aug 9, 2003
    #1
    1. Advertising

  2. Hi,

    Look for the last modification date/time for the file. Install a timer to
    read this date/time every xxx seconds or minutes
    I f the modification has been changed read the file until the end is reached
    i.e.

    ......
    read file until end
    fill variable lastmodified with last time file modified;
    ......
    while(true)
    {
    signal SIGALRM, timerEvent );
    alarm( 5 ) // every 5 seconds
    }
    .......

    void timerEvent()
    {
    struct stat st;

    // fd file descriptor open file
    fstat( fd, &st );
    if( st.st_mtime != lastmodified )
    {
    read file until end of file
    }
    lastmodified = st.st_mtime;
    }


    "Count Dracula" <> schreef in bericht
    news:...
    > Is there a way to write a c++ program that will
    > print out the last few lines of a file without reading
    > the whole file? The implementations of 'tail' I have
    > seen all appear to be system dependent. I am looking for
    > a standard (portable) c++ solution that will do just a
    > fraction of tail's functionality. To make a long story short,
    > I am looking for suggestions that may help me improve the
    > speed of the following implementation for long input files:
    >
    > /*
    > Command line utility to display the last few lines of a text file.
    >
    > Usage: (1) tail <filename>
    > (2) tail <filename> <number of lines>
    >
    > <filename> is the name of the file whose last few lines you want to
    > display
    > <number of lines> is the number of lines you want to display
    > (default is NumberOfLines)
    >
    > Implementation note: this is an inefficient implementation that
    > reads the whole file
    > only to display a few lines from the end of the file.
    > */
    >
    > #include <string>
    > #include <iostream>
    > #include <fstream>
    > #include <cstdlib>
    > #include <deque>
    >
    > // Forward declarations
    > bool writetail(const std::string & filename, long numlines);
    > void usage(long NumberOfLines);
    >
    > int main (int argc, char** argv)
    > {
    > const long NumberOfLines = 10;
    > long numlines;
    > std::string filename;
    > switch (argc)
    > {
    > case 2:
    > filename = argv[1];
    > numlines = NumberOfLines;
    > break;
    > case 3:
    > filename = argv[1];
    > numlines = strtol(argv[2], NULL, 10);
    > if (numlines <= 0 || errno == ERANGE)
    > {
    > std::cerr << argv[0] << ": error in second command line
    > argument" << '\n';
    > usage(NumberOfLines);
    > return 1;
    > }
    > break;
    > default:
    > std::cerr << argv[0] << ": missing command line arguments" <<
    > '\n';
    > usage(NumberOfLines);
    > return 1;
    > }
    > bool status = writetail(filename, numlines);
    > if (!status)
    > {
    > std::cerr << argv[0] << ": execution errors" << '\n';
    > usage(NumberOfLines);
    > return 1;
    > }
    > return 0;
    > }
    >
    > bool writetail(const std::string & filename, long numlines)
    > {
    > std::ifstream input(filename.c_str());
    > if (!input)
    > {
    > std::cerr << "writehead: error opening file: " << filename <<
    > '\n';
    > return false;
    > }
    > std::string s;
    > std::deque<std::string> lines;
    > long kount = 0;
    > while (std::getline(input, s))
    > {
    > lines.push_back(s);
    > ++kount;
    > if (kount == numlines) break;
    > }
    > while (std::getline(input, s))
    > {
    > lines.pop_front();
    > lines.push_back(s);
    > }
    > std::deque<std::string>::iterator p;
    > for (p = lines.begin(); p < lines.end(); ++p)
    > std::cout << *p << '\n';
    > input.close();
    > return true;
    > }
    >
    > void usage(long NumberOfLines)
    > {
    > std::cerr << "usage: tail <filename> <number of lines (optional)>\n"
    > <<
    > " <filename> is the name of the file whose last
    > few lines you want to display\n" <<
    > " <number of lines> is the number of lines you
    > want to display (default is " <<
    > NumberOfLines << ")\n";
    > }
    Johan den Boer, Aug 10, 2003
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Owen Zhang
    Replies:
    0
    Views:
    281
    Owen Zhang
    Sep 19, 2007
  2. Owen Zhang

    What is best way to implement "tail"?

    Owen Zhang, Sep 19, 2007, in forum: C Programming
    Replies:
    0
    Views:
    337
    Owen Zhang
    Sep 19, 2007
  3. Owen Zhang
    Replies:
    26
    Views:
    788
    Keith Thompson
    Sep 21, 2007
  4. Terry Michaels

    Tail Call Optimization (Tail Recursion)

    Terry Michaels, Apr 18, 2011, in forum: Ruby
    Replies:
    16
    Views:
    304
    Robert Klemme
    Apr 20, 2011
  5. Replies:
    2
    Views:
    44
    Mark H Harris
    May 13, 2014
Loading...

Share This Page