windows系统日志中记录了系统中硬件、软件和系统问题的相关信息,同时可监控系统中发生的事件。因此当系统崩溃导致一些异常现象发生时可通过系统日志来找出错误发生的原因。那么对于应用软件来说,如果也提供类似的日志文件,帮助我们监控软件运行过程中的各种状态信息,这样当软件出现异常时也便于查找原因。而且在软件开发过程中可以结合日志解决软件调试过程中出现的各种问题,从而提高开发效率。基于此本文对vs下写日志的各种方法进行了总结。

日志中无非记录了两个主要内容:一个是事件发生的时间,一个是事件本身。而将内容写入文件的方式无非有以下几种:

1、windows 有关文件操作的API:fopen(),fwrite(),fputs(),fprintf(),fclose()等;

2、c++中的IO库:fstream,ifstream,ofstream;

3、c++中的文件操作类CFile,CStdioFile等;

4、用户自定义文件类。

我们主要采用两种方式来实现写日志功能,一个是将写日志功能通过封装到一个函数中,当需要将数据写入日志文件时就调用此函数。另一个是自己实现日志文件类,在程序中一开始就构建日志文件对象,当需要写入日志时通过调用类的成员函数实现日志写入功能。

(一)写日志函数logFile

根据前面所述,此函数实现的功能应为:将当前时间及事件信息写入日志。函数声明如下:

void logFile(char* logfileName, char* data);

参数说明:第一个参数为日志文件名称,第二个参数为写入的信息数据(如错误,警告等)。

函数实现:

FILE *fp;

SYSTEMTIME st;

GetLocalTime(&st);

fp=fopen(logfileName,"a");

if(fp==0)

{

return;

}

fprintf(fp, "%d-%d-%d %d:%d:%d :%s\r\n", st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond, str);

fclose(fp);

说明:函数中先获取系统时间,然后利用fprintf将信息格式化写入日志中。

(二)日志文件类

可基于CFile等已有的文件类编写,也可完全自己编写。本文中采用后者。

文件类声明(头文件):

#pragma once
class LogFile
{
protected:
    CRITICAL_SECTION _csLock;
    char * _szFileName;
    HANDLE _hFile;
    bool OpenFile();//打开文件, 指针到文件尾
    DWORD Write(LPCVOID lpBuffer, DWORD dwLength);
    virtual void WriteLog( LPCVOID lpBuffer, DWORD dwLength);//写日志, 可以扩展修改
    void Lock()  {::EnterCriticalSection(&_csLock); }
    void Unlock() {::LeaveCriticalSection(&_csLock);} 
    char szFileSuffix[32]; //文件后缀
public:
    LogFile(char*szFileName);
    virtual ~LogFile();
    const char * GetFileName()
    {
        return _szFileName;
    }

void SetFileName(const char *szName);//修改文件名, 同时关闭上一个日志文件
    bool IsOpen()
    {
        return _hFile != INVALID_HANDLE_VALUE;
    }

void Close();
    void Log(LPCVOID lpBuffer, DWORD dwLength);//追加日志内容
    void Log(const char *szText){
        Log(szText, strlen(szText));}
    void Log(CString str);
    void Log(TCHAR *buffer);
private://屏蔽函数
    LogFile(const LogFile&);
    LogFile&operator = (const LogFile&);
};

类实现(源文件):

#include "StdAfx.h"
#include "LogFile.h"

LogFile::LogFile(char*szFileNameParam)
{
    memset(szFileSuffix,0,sizeof(szFileSuffix));
    strcat_s(szFileSuffix,szFileNameParam);  //文件后辍,不带日期
    _szFileName = NULL;
    _hFile = INVALID_HANDLE_VALUE;
    ::InitializeCriticalSection(&_csLock);

//求出当前日期
    time_t now;
    time(&now);
    char szCurDate[256] = {0};
    struct tm newtime;
    localtime_s(&newtime,&now);
    strftime(szCurDate,19,"%Y%m",&newtime);

char szFileName[64] = {0};
    strcat_s(szFileName,10,szCurDate); //日期在前面
    strcat_s(szFileName,szFileSuffix);  //追加文件名
    SetFileName(szFileName);
}

//-------------------------------------------------------------------------
LogFile::~LogFile()
{
    ::DeleteCriticalSection(&_csLock);
    Close();
    if(_szFileName)
        delete [] _szFileName;
}
//-------------------------------------------------------------------------
bool LogFile::OpenFile()
{
    if(IsOpen())
        return true;
    if(!_szFileName)
        return false;

_hFile = CreateFileA(
        _szFileName,
        GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

if(!IsOpen() && GetLastError() == 2)//打开不成功, 且因为文件不存在, 创建文件
        _hFile = CreateFileA(
        _szFileName,
        GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

if(IsOpen())
        SetFilePointer(_hFile, 0, NULL, FILE_END);
    return IsOpen();
}
//-------------------------------------------------------------------------
DWORD LogFile::Write(LPCVOID lpBuffer, DWORD dwLength)
{
    DWORD dwWriteLength = 0;
    if(IsOpen())
        WriteFile(_hFile, lpBuffer, dwLength, &dwWriteLength, NULL);
    return dwWriteLength;
}
//-------------------------------------------------------------------------
void LogFile::WriteLog( LPCVOID lpBuffer, DWORD dwLength)
{
    DWORD dwWriteLength;
    char buf[1024]={0};
    strcat_s(buf,1000,(char*)lpBuffer);
    if(IsOpen())
    {
        time_t now;
        time(&now);
        char temp[1024];
        struct tm newtime;
        localtime_s(&newtime,&now);
        memset(temp,0,sizeof(temp));
        strftime(temp, 64, "%Y-%m-%d %H:%M:%S   :", &newtime);
        strcat_s(temp,128,"   :");
        strcat_s(temp,1024,buf);
        WriteFile(_hFile, temp,strlen(temp), &dwWriteLength, NULL);
        WriteFile(_hFile, "\r\n",2, &dwWriteLength, NULL);
        FlushFileBuffers(_hFile); //存硬盘

}
    else
    {
        ;
    }
}
//-------------------------------------------------------------------------
void LogFile::SetFileName(const char *szName)
{
    //assert(szName);

if(_szFileName != NULL)
    {
        //AfxMessageBox(_T("_szFileName is NULL"));
        delete []_szFileName;
    }
    Close();
    int len = strlen(szName);
    _szFileName = new char[32];
//    assert(_szFileName);
    strcpy_s(_szFileName,30,szName);
}
//-------------------------------------------------------------------------
void LogFile::Close()
{
    if(IsOpen())
    {
        CloseHandle(_hFile);
        _hFile = INVALID_HANDLE_VALUE;
    }
}
//-------------------------------------------------------------------------
void LogFile::Log(LPCVOID lpBuffer, DWORD dwLength)
{
//    assert(lpBuffer);
    __try
    {
        Lock();

//算出现在应该写日志的文件名
        time_t now;
        time(&now);
        char szCurDate[256] = {0};
        struct tm newtime;
        localtime_s(&newtime,&now);
        strftime(szCurDate,19,"%Y%m",&newtime);
        char szCurFileName[64] = {0};
        strcat_s(szCurFileName,10,szCurDate); //日期在前面
        strcat_s(szCurFileName,szFileSuffix);  //追加文件名
        if(!PathFileExistsA(szCurFileName))
            SetFileName(szCurFileName);

if(OpenFile())
            WriteLog(lpBuffer, dwLength);
    }
    __finally
    {
        Unlock();
    }
}

void LogFile::Log(TCHAR *buffer)
{
    CT2A buf_str(buffer);
    Log(buf_str);
}
void LogFile::Log(CString str)
{
    Log(str.GetBuffer());
}

(出处:http://www.cnblogs.com/zhangdongsheng/)

日志文件类的使用:程序初始化时构建日志文件对象,需要将某些信息写入日志时调用Log()方法实现写入。

vs2010中写日志文件的几种方法相关推荐

  1. Linux系统中运行.sh文件的几种方法

    在Linux系统中执行.sh文件的几种方法: 1. cd到.sh文件所在的目录,然后执行./xxx.sh   [前提:该./sh文件要有可执行的权限,chmod u+x xxx.sh]  2. 在任何 ...

  2. matlab中读文件的行数_Matlab中读取txt文件的几种方法

    Matlab中读取txt文件的几种方法 一.纯数据文件(没有字母和中文,纯数字) 对于这种txt文档,从matalb中读取就简单多了 例如test.txt文件,内容为"17.901 -1.1 ...

  3. matlab中如何读写txt,Matlab中读取txt文件的几种方法

    Matlab中读取txt文件的几种方法 matlab读取文本文件的几种函数: 1.load--适合读取纯数据文本: 2.importdata--只读取数据,自动省略数据格式前后的字符,超大文件不适合: ...

  4. HTML中写CSS代码的两种方法

    在HTML中写CSS代码也两种方法. 写在HTML标签里 使用CSS前 <h1>这是一个标题 </h1> 使用CSS后 <h1 style="color:red ...

  5. spark 读取ftp_在 Shell 中下载 ftp 文件的几种方法

    FTP 是 File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文传协议".用于 Internet 上的控制文件的双向传输.同时,它也是一个应用程 ...

  6. Linux 实时查看日志文件的 4 种方法

    来源 | GOPS 全球运维大会 2021 · 上海站 在 Linux 下如何才能实时查看日志内容呢?有很多工具可以帮助我们在文件持续修改的同时输出文件内容,最常用的莫过于 tail 命令了. 1. ...

  7. matlab怎么读txt文件字符串,Matlab中读取txt文件的几种方法

    一.纯数据文件(没有字母和中文,纯数字) a=importdata('*.txt');%%%*为所存的文件名 a1=a.data;%%%文件中的数字 a2=a.textdata;%%%文件中的非数字 ...

  8. Matlab中读取txt文件的几种方法

    matlab读取文本文件的几种函数: 1.load--适合读取纯数据文本: 2.importdata--只读取数据,自动省略数据格式前后的字符,超大文件不适合: 3.textread.textscan ...

  9. flash air中读取本地文件的三种方法

    actionscript中读取本地文件操作有两种代码如下 1.使用File和FileStream两个类,FileStream负责读取数据的所以操作:(同步操作) ? 1 2 3 4 5 var str ...

最新文章

  1. mysql数据库三级分类_5.在 MySQL数据库中,以下数据库对象与数据库三级模式对应关系正确的是?...
  2. android开发常见的设计模式,Android开发有哪些常用设计模式?
  3. A.DongDong破密码
  4. 成长型公司的存储架构
  5. 域用户更改密码提示拒绝访问_AD域中的ACL攻防探索
  6. 队列处理高并发_高并发场景下缓存处理的一些思路
  7. 【脑电信号】基于matlab小波变换睡眠脑电信号监测【含Matlab源码 595期】
  8. VBA Mid()函数 截取字符串 - VBA函数学习笔记(一)
  9. 【Unity3D】Photon环境搭建
  10. 使用eclipse打包app以及AndroidStudio和Eclipse中app签名修改等问题(SH1和MD5)
  11. 安装TortoiseSVN报could not write value to key的错误解决方案
  12. 谷歌浏览器打开阅读清单
  13. 解决高德地图闪屏黑屏
  14. 也就整了一万字的「数据指标体系」指南。
  15. 用Hydra工具暴力破解Windows7管理员密码并访问它的共享服务
  16. 虚拟服务器忘记密码,win7系统下VMware虚拟机忘记开机密码的解决方法
  17. SecureCRT Home End键
  18. 备份计算机软件,如何备份电脑里面的软件
  19. 每天上下班之前读一遍,直到铭记在心……
  20. 什么是计算机立体化教程,全国计算机等级考试立体化应试教程

热门文章

  1. iOS自动化之WDA(WebDriverAgent)安装及踩坑(本文仅作经验记录,原WDA已经废弃,详细请看更新说明)
  2. 以TTX连萌来多层次分析游戏破解
  3. 想知道B站献礼视频《后浪》大家都在讨论什么吗?
  4. 我的创作纪念日【在分享中感受被需要的价值】
  5. 蛮荒搜神记服务器在维护,宏伟神话故事落幕 《蛮荒搜神记》宣布停止运营
  6. 团体程序设计天梯赛 L2-035 完全二叉树的层序遍历
  7. 5+app处理返回键问题,后退按钮返回上一页
  8. 《凤凰架构》——架构路上的一本好书
  9. 素质拓展之1到30看图猜数并排序
  10. Linux内核驱动学习(一)编写最简单Linux内核模块HelloWorld