监控log文件变化进行读出变化的内容供分析的源码类
头文件:
#pragma once
//#define DEBUG_MONITORING_FILE_CHANGES
#ifdef DEBUG_MONITORING_FILE_CHANGES
#include "CiteConsole.h"
#endif
//定义获取到新的内容事件
typedef void (CALLBACK* ONREADNEWCONTENT)(void* pOwner, const CString* strBuf, DWORD dwBufLen);
class CLogFileMonitor
{
public:
CLogFileMonitor(void);
public:
~CLogFileMonitor(void);
/*--向上层的回调事件--*/
//读取到新的数据事件,回调函数
ONREADNEWCONTENT OnReadNewContent;
private:
//线程退出事件句柄
HANDLE m_exitThreadEvent;
//线程句柄
HANDLE m_MonitoringThreadHandle;
//父对象句柄
void * m_pOwner;
private:
static DWORD WINAPI MonitoringThreadFunc(LPVOID lparam);
BOOL Close();
// 文件读取的成员和方法
private:
LONGLONG m_lOff; //记录读取的文件的位置
ULONGLONG m_lActual;//seek实际到达的文件位置
CString m_strFilePathName;
CStdioFile m_file;
BOOL m_blOpenSucess;
void OpenFile();
void ReadNewLine();
public:
void Init(CString strFileName, void* pOwner, void* OnReadNewContentFun);
};
源文件
#include "StdAfx.h"
#include "LogFileMonitor.h"
CLogFileMonitor::CLogFileMonitor(void)
{
OnReadNewContent = NULL;
m_pOwner = NULL;
m_lOff = 0;
m_lActual = 0;
m_blOpenSucess =FALSE;
//创建线程退出事件句柄
CString strEventName;
strEventName.Format(_T("EVENT_FILE_MONITOR_THREAD%d"), this);
m_exitThreadEvent = CreateEvent(NULL,FALSE,FALSE, strEventName);
//创建通讯线程
m_MonitoringThreadHandle = CreateThread(NULL,0,MonitoringThreadFunc,this,0,NULL);
}
CLogFileMonitor::~CLogFileMonitor(void)
{
Close();
//关闭线程退出事件句柄
CloseHandle(m_exitThreadEvent);
Sleep(1000);
if (m_blOpenSucess && m_file )
{
m_file.Close();
printf("文件关闭");
m_blOpenSucess = FALSE;
}
m_blOpenSucess =FALSE;
}
DWORD WINAPI CLogFileMonitor::MonitoringThreadFunc(LPVOID lparam)
{
CLogFileMonitor *pThis = (CLogFileMonitor*)lparam;
while (TRUE)
{
//收到退出事件,结束线程
if (WaitForSingleObject(pThis->m_exitThreadEvent,0) == WAIT_OBJECT_0)
{
break;
}
pThis->ReadNewLine();
}
TRACE(L"CMonitoringFileChanges线程退出\n");
return 0;
}
void CLogFileMonitor::Init(CString strFileName,void* pOwner, void* OnReadNewContentFun)
{
m_strFilePathName = strFileName;
m_pOwner = pOwner;
OnReadNewContent = (ONREADNEWCONTENT)OnReadNewContentFun;
}
void CLogFileMonitor::OpenFile()
{
m_blOpenSucess = m_file.Open(m_strFilePathName, CFile::modeRead |CFile::shareDenyNone);
if (!m_blOpenSucess)
{
printf("监控log文件失败");
}
}
void CLogFileMonitor::ReadNewLine()
{
if(!m_blOpenSucess)
{
Sleep(100);
OpenFile();
if (!m_blOpenSucess)
{
return;
}
}
if (m_lOff != m_lActual)
{
Sleep(200);
}
else
{
Sleep(300);
}
CString strText = _T("");
CString szLine = _T("");
if (m_file ==NULL)
{
return;
}
if (!m_blOpenSucess)
{
return;
}
if (m_file.m_pStream != NULL)
{
m_lActual = m_file.Seek(m_lOff,CFile::begin);
//逐行读取字符串
while( m_file.ReadString( szLine ) )
{
if (m_pOwner && !szLine.IsEmpty())
{
OnReadNewContent(m_pOwner, &szLine, m_lActual);
}
szLine = _T("");
}
m_lOff = m_file.Seek(0, CFile::current);
}
}
BOOL CLogFileMonitor::Close()
{
//发送通讯线程结束事件
SetEvent(m_exitThreadEvent);
//等待1秒,如果读线程没有退出,则强制退出
if (WaitForSingleObject(m_MonitoringThreadHandle,1000) == WAIT_TIMEOUT)
{
TerminateThread(m_MonitoringThreadHandle,0);
TRACE(L"强制终止客户端线程\n");
}
m_MonitoringThreadHandle = NULL;
//关闭文件,释放资源
return TRUE;
}
使用的时候,实现回调就可以在回调里面获取最新获取的变化量;
还有可以改进的思路就是:
每次都进行打开,并且每次都关闭,这样可以尽量不影响原来其他程序对log文件的操作。