lnkTail.h
/***********************************************************
* 文件名称: lnkTail.h
* 功能描述: 类似linux系统tailf命令的功能
* 实现原理: 每次比较文件大小,发生变化则打开文件偏移到
* 上一次记录的文件大小处再读取文件内容
* 主要实现: 另起线程将每次读取的内容存入队列,供其它调
* 用模块实时监控日志。
* 历史信息: lnk 创建 2015.10.25
************************************************************/
#ifndef _LNK_TAIL_H_
#define _LNK_TAIL_H_
#include <string>
#include <queue>
using namespace std;
typedef struct tag_Line{
string sText; //行内容
string sTime; //读取时的时间
}Line;
class Tail{
public:
void SetFileName(string sPramFileName); //设置要tailf的文件名称
string GetFileName(); //获取文件名称
void TailFile(); //tailf文件
Line GetLine(); //获取行
bool Empty(); //判断是否有新行加入队列
private:
string sFileName; //文件名称
queue<Line> qLines; //行队列
};
#endif //_LNK_TAIL_H_
/***********************************************************
* 文件名称: lnkTail.cpp
* 功能描述: 类似linux系统tailf命令的功能的实现
* 历史信息: lnk 创建 2015.10.25
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <sys/stat.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include "lnkTail.h"
#define _(s) s
//tailf线程参数结构
typedef struct tag_TailPram{
char *pcFileName;
queue<Line> *pqLines;
}TailPram;
//函数功能:获取文件大小
//参数说明:const char * [IN] 文件名称
//返 回 值:size_t 文件大小
//历史信息:lnk 创建 2015.10.25
static size_t filesize(const char *filename)
{
struct stat sb;
if (!stat(filename, &sb)) return sb.st_size;
return 0;
}
//函数功能:设置文件名称
//参数说明:string [IN] 文件名称
//返 回 值:无
//历史信息:lnk 创建 2015.10.25
void Tail::SetFileName(string sPramFileName)
{
this->sFileName = sPramFileName;
}
//函数功能:获取文件名称
//参数说明:无
//返 回 值:string 文件名称
//历史信息:lnk 创建 2015.10.25
string Tail::GetFileName()
{
return this->sFileName;
}
//函数功能:获取文件名称
//参数说明:TailPram * 线程参数
//返 回 值:-1失败 0线程结束
//历史信息:lnk 创建 2015.10.25
void* TailFileToQueue(void *ptr)
{
char cBuf[BUFSIZ];
size_t osize, nsize;
FILE *pf;
int nCnt = 0;
TailPram *fileAndQue = (TailPram *)ptr;
for (osize = filesize(fileAndQue->pcFileName);;)
{
nsize = filesize(fileAndQue->pcFileName);
if (nsize != osize) {
if (!(pf = fopen(fileAndQue->pcFileName, "r"))) {
fprintf(stderr, _("Cannot open \"%s\" for read\n"), fileAndQue->pcFileName);
return (void *)-1;
}
if (!fseek(pf, osize, SEEK_SET))
{
while ((nCnt = fread(cBuf, 1, sizeof(cBuf), pf)) > 0)
{
//fwrite(cBuf, 1, nCnt, stdout);
time_t lt;
Line stNewLine;
stNewLine.sText = cBuf;
lt = time(NULL);
stNewLine.sTime = ctime(<);
fileAndQue->pqLines->push(stNewLine);
//printf("%s %s",stNewLine.sText.c_str(), stNewLine.sTime.c_str());
}
}
//fflush(stdout);
fclose(pf);
osize = nsize;
}
usleep(250000);
}
return (void*)0;
}
//函数功能:tail文件
//参数说明:无
//返 回 值:无
//历史信息:lnk 创建 2015.10.25
void Tail::TailFile()
{
pthread_t pid;
TailPram *fileAndQue = new TailPram;
fileAndQue->pcFileName = (char *)malloc(strlen(this->sFileName.c_str()));
strcpy(fileAndQue->pcFileName, this->sFileName.c_str());
fileAndQue->pqLines = &this->qLines;
int ret = pthread_create(&pid, NULL, TailFileToQueue, (void*)fileAndQue);
if(ret)
{
fprintf(stderr, _("Cannot create pthread!\n"));
return;
}
//pthread_join(pid, NULL);
//fprintf(stderr, _("tail stop"));
}
//函数功能:是否监控到新行
//参数说明:无
//返 回 值:true false
//历史信息:lnk 创建 2015.10.25
bool Tail::Empty()
{
return this->qLines.empty();
}
//函数功能:获取行
//参数说明:无
//返 回 值:Line
//历史信息:lnk 创建 2015.10.25
Line Tail::GetLine()
{
Line lRes;
if(!this->qLines.empty())
{
lRes = this->qLines.front();
this->qLines.pop();
}
return lRes;
}
mian.cpp 主要写写怎么使用!
#include <iostream>
#include <stdlib.h>
#include "lnkTail.h"
int main(int argc, char **argv)
{
Tail myTail;
if(argc != 2)
{
cout<<"use like tail filename!"<<endl;
return -1;
}
myTail.SetFileName(argv[1]); //tailf文件名由参数传入
myTail.TailFile(); //启动tailf线程
while(1) //循环获取监控的新行
{
if(!myTail.Empty())
{
Line tmp = myTail.GetLine();
cout<<tmp.sText<<tmp.sTime;
}
else
{
usleep(250000);
}
}
return 0;
}
当然还需要在合适的地方把内存给释放了,懒得改了。有时间再看下。。