最近在做网页爬虫的测试,需要通过apache的access-log来验证爬虫的行为,就想到了用类似linux的tail命令实现方式来实现。这里先把代码贴出来:
#include
<
stdio.h
>
#include < stdlib.h >
#include < unistd.h >
#include < malloc.h >
#include < sys / stat.h >
static size_t filesize( const char * filename) {
struct stat sb;
if ( ! stat(filename, & sb))
return sb.st_size;
return 0 ;
}
static void tailf( const char * filename, int lines) {
char ** buffer;
int head = 0 ;
int tail = 0 ;
FILE * str;
int i;
if ( ! (str = fopen(filename, " r " ))) {
fprintf(stderr, " Cannot open \"%s\" for read\n " , filename);
perror( "" );
exit( 1 );
}
buffer = ( char ** ) malloc(lines * sizeof ( * buffer));
for (i = 0 ; i < lines; i ++ )
buffer[i] = ( char * ) malloc(BUFSIZ + 1 );
while (fgets(buffer[tail], BUFSIZ, str)) {
if ( ++ tail >= lines) {
tail = 0 ;
head = 1 ;
}
}
// the method here is very smart, if variable head is set, that is to say the file is longer than 10 lines,
// and the first line of the last 10 lines is start from the index tail, and the last line is at index tail-1
if (head) {
for (i = tail; i < lines; i ++ )
fputs(buffer[i], stdout);
for (i = 0 ; i < tail; i ++ )
fputs(buffer[i], stdout);
} else {
for (i = head; i < tail; i ++ )
fputs(buffer[i], stdout);
}
fflush(stdout);
for (i = 0 ; i < lines; i ++ )
free(buffer[i]);
free(buffer);
}
int main( int argc, char ** argv) {
char buffer[BUFSIZ];
size_t osize, nsize;
FILE * str;
const char * filename;
int count;
if (argc != 2 ) {
fprintf(stderr, " Usage: tailf logfile\n " );
exit( 1 );
}
filename = argv[ 1 ];
tailf(filename, 10 );
for (osize = filesize(filename);;) {
nsize = filesize(filename);
if (nsize != osize) {
if ( ! (str = fopen(filename, " r " ))) {
fprintf(stderr, " Cannot open \"%s\" for read\n " , filename);
perror(argv[ 0 ]);
exit( 1 );
}
if ( ! fseek(str, osize, SEEK_SET))
while ((count = fread(buffer, 1 , sizeof (buffer), str)) > 0 )
fwrite(buffer, 1 , count, stdout);
fflush(stdout);
fclose(str);
osize = nsize;
}
usleep( 250000 ); /* 250mS */
}
return 0 ;
#include < stdlib.h >
#include < unistd.h >
#include < malloc.h >
#include < sys / stat.h >
static size_t filesize( const char * filename) {
struct stat sb;
if ( ! stat(filename, & sb))
return sb.st_size;
return 0 ;
}
static void tailf( const char * filename, int lines) {
char ** buffer;
int head = 0 ;
int tail = 0 ;
FILE * str;
int i;
if ( ! (str = fopen(filename, " r " ))) {
fprintf(stderr, " Cannot open \"%s\" for read\n " , filename);
perror( "" );
exit( 1 );
}
buffer = ( char ** ) malloc(lines * sizeof ( * buffer));
for (i = 0 ; i < lines; i ++ )
buffer[i] = ( char * ) malloc(BUFSIZ + 1 );
while (fgets(buffer[tail], BUFSIZ, str)) {
if ( ++ tail >= lines) {
tail = 0 ;
head = 1 ;
}
}
// the method here is very smart, if variable head is set, that is to say the file is longer than 10 lines,
// and the first line of the last 10 lines is start from the index tail, and the last line is at index tail-1
if (head) {
for (i = tail; i < lines; i ++ )
fputs(buffer[i], stdout);
for (i = 0 ; i < tail; i ++ )
fputs(buffer[i], stdout);
} else {
for (i = head; i < tail; i ++ )
fputs(buffer[i], stdout);
}
fflush(stdout);
for (i = 0 ; i < lines; i ++ )
free(buffer[i]);
free(buffer);
}
int main( int argc, char ** argv) {
char buffer[BUFSIZ];
size_t osize, nsize;
FILE * str;
const char * filename;
int count;
if (argc != 2 ) {
fprintf(stderr, " Usage: tailf logfile\n " );
exit( 1 );
}
filename = argv[ 1 ];
tailf(filename, 10 );
for (osize = filesize(filename);;) {
nsize = filesize(filename);
if (nsize != osize) {
if ( ! (str = fopen(filename, " r " ))) {
fprintf(stderr, " Cannot open \"%s\" for read\n " , filename);
perror(argv[ 0 ]);
exit( 1 );
}
if ( ! fseek(str, osize, SEEK_SET))
while ((count = fread(buffer, 1 , sizeof (buffer), str)) > 0 )
fwrite(buffer, 1 , count, stdout);
fflush(stdout);
fclose(str);
osize = nsize;
}
usleep( 250000 ); /* 250mS */
}
return 0 ;
}