By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,509 Members | 1,306 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,509 IT Pros & Developers. It's quick & easy.

A better way to tail a file

P: n/a
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";
}
Jul 19 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
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" <lk**@esinet.net> schreef in bericht
news:fc**************************@posting.google.c om...
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";
}

Jul 19 '05 #2

P: n/a
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" <lk**@esinet.net> schreef in bericht
news:fc**************************@posting.google.c om...
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";
}

Jul 19 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.