VC6下使用API实现自带缓存的写文件类

介绍了一种带缓存的日志记录类CBufferLog,通过自定义缓存大小提高写入效率,较CStdioFile快约一倍。支持文件长度达64位长,使用系统API直接写入文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     这是【带缓存的log写出类】的改进版本;效率比CStdioFile快一倍左右;使用系统API写出文件;使用自带缓存不使用系统文件buffer。

   支持文件最大长度是64位长,即两个DWORD长byte数据。

 

非精确测试,测试结果,单位毫秒,前面是CBufferLog,后面是CStdiofile:

debug版下大致:
714M数据耗时分别是20289和47000;
476M数据耗时分别是13344和26735,
238M数据耗时分别是4961和11633;


感谢cnzdgs 在为期一周的探索过程中的不厌烦的帮助!

优快云帖子地址:http://topic.youkuaiyun.com/u/20080827/09/ea598ffd-340e-41ac-ad84-fd87cf21cce8.html?279638131

 

   因为活又来了,以后有时间再慢慢完善。

TODOList:

1. 使用VirtualAlloc分配页面文件整数倍大小的buffer;

2. 文件相关其他操作函数的支持

3. 使用磁盘映射文件写log还未尝试

 

所有源码如下(沙漠孤狐 版权所有, Boythl#163.com):

 

  1. // BufferLog.h: interface for the CBufferLog class.
  2. //目标:
  3. //  1.带缓冲区的文件输出类
  4. //  2.可自定义缓冲区大小
  5. //  3.可重定义缓冲区大小
  6. //  4.缓冲区满时自动写到文件里
  7. //////////////////////////////////////////////////////////////////////
  8. #if !defined(AFX_BUFFERLOG_H__0F83C182_4C70_44B0_9F53_D66F43E55FD8__INCLUDED_)
  9. #define AFX_BUFFERLOG_H__0F83C182_4C70_44B0_9F53_D66F43E55FD8__INCLUDED_
  10. #if _MSC_VER > 1000
  11. #pragma once
  12. #endif // _MSC_VER > 1000
  13. #include <io.h>
  14. const DWORD SECTOR_SIZE = 512;//the sector size is 512 bytes
  15. const UCHAR CHAR_LN[] = {'/r''/n'}; //换行符
  16. class CBufferLog  
  17. {
  18. public:     
  19.     CBufferLog(DWORD dwBufferSize = 10000);//单位扇区,默认缓存10000个扇区
  20.     virtual ~CBufferLog();
  21.     virtual void WriteLog( const void* lpBuf, DWORD dwCount );//写log到缓存
  22.     inline virtual void WriteLogLn( const void* lpBuf, DWORD dwCount )//写一行(自动加换行符)到缓存
  23.     { WriteLog(lpBuf, dwCount); WriteLog(CHAR_LN, 2); }
  24.     inline virtual void WriteLogLn( )//写入一空行
  25.     { WriteLog(CHAR_LN, 2); }
  26.     inline void WriteString(const CString& sz){this->WriteLog((LPCTSTR)sz, sz.GetLength());}
  27.     BOOL Open( LPCTSTR lpszFileName, bool Apped = false );//打开log文件,Append是否覆盖已有内容
  28.     void Close( ); //关闭log文件
  29.     DWORD GetPosition();//32位的获取文件指针位置
  30.     DWORD GetPosition(DWORD& High32);//64位的获取文件指针位置
  31.     inline LPCTSTR GetFilePath() const { return this->m_Path; }
  32.     inline DWORD SeekToEnd(){return SetFilePointer(this->m_Handle, 0L, NULL, FILE_END ); }
  33.     inline DWORD SeekToBegin(){return SetFilePointer(this->m_Handle, 0L, NULL, FILE_BEGIN ); }
  34. protected:
  35.     inline virtual void Flush()//输出缓冲区内容
  36.     { 
  37.         this->Write(this->m_dwCurPos); 
  38.         this->m_dwCurPos = 0;
  39.         this->m_dwFreeLen = this->m_BufferSize;
  40.     }
  41.     
  42.     virtual BOOL Write(DWORD dwLen); //写缓冲区内容到磁盘    
  43.     DWORD  m_BufferSize;                //缓存尺寸
  44.     char*  m_Buffer;                    //缓存
  45.     DWORD  m_dwCurPos;                  //当前缓冲区指针位置
  46.     DWORD  m_dwFreeLen;                 //可用缓冲数 
  47.     HANDLE m_Handle;                    //file handle
  48.     CHAR   m_Path[MAX_PATH];            //file path 
  49. private:
  50.     DWORD  m_dwByteWrittern;
  51.     LPOVERLAPPED m_pOverLapped;
  52.     DWORD  m_dwOffsetLow;               //文件指针偏移量低位
  53.     DWORD  m_dwOffsetHigh;              //文件指针偏移量高位
  54. };
  55. #endif // !defined(AFX_BUFFERLOG_H__0F83C182_4C70_44B0_9F53_D66F43E55FD8__INCLUDED_)
  1. // BufferLog.cpp: implementation of the CBufferLog class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "BufferLog.h"
  6. #include <fcntl.h>
  7. #include <sys/stat.h>
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. //////////////////////////////////////////////////////////////////////
  14. // Construction/Destruction
  15. //////////////////////////////////////////////////////////////////////
  16. CBufferLog::CBufferLog(DWORD dwBufferSize/* = 10000*/)
  17. {
  18.     ASSERT(dwBufferSize != 0);
  19.     this->m_dwFreeLen = this->m_BufferSize = dwBufferSize * SECTOR_SIZE;
  20.     this->m_dwByteWrittern = this->m_dwCurPos = 0;  
  21.     this->m_Buffer = new char[m_BufferSize];
  22.     memset(this->m_Buffer, 0, m_BufferSize);
  23.     memset(m_Path, 0, MAX_PATH);
  24.     this->m_Handle = NULL;
  25.     this->m_pOverLapped = new OVERLAPPED;
  26.     m_pOverLapped->hEvent = NULL;
  27.     m_pOverLapped->Internal = m_pOverLapped->InternalHigh =
  28.         m_pOverLapped->Offset = m_pOverLapped->OffsetHigh = 0;
  29.     m_pOverLapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  30.     this->m_dwOffsetHigh = this->m_dwOffsetLow = 0;
  31. }
  32. BOOL CBufferLog::Open( LPCTSTR lpszFileName, 
  33.                       bool Apped /*= false*/ )
  34. {
  35.     if (this->m_Handle)
  36.     {
  37.         _ASSERTE(("The file isn't closed, can't open two times!/n", NULL));
  38.         return FALSE;
  39.     }
  40.     
  41.     this->m_dwFreeLen = this->m_BufferSize;
  42.     this->m_dwByteWrittern = this->m_dwCurPos = 0;  
  43.     memset(this->m_Buffer, 0, m_BufferSize);
  44.     memset(m_Path, 0, MAX_PATH);
  45.     m_pOverLapped->hEvent = NULL;
  46.     m_pOverLapped->Internal = m_pOverLapped->InternalHigh =
  47.         m_pOverLapped->Offset = m_pOverLapped->OffsetHigh = 0;
  48.     this->m_dwOffsetLow = this->m_dwOffsetHigh = 0;
  49.     
  50.     int nCreateFlag = Apped 
  51.         ? OPEN_ALWAYS //Opens the file, if it exists.
  52.                       //If the file does not exist, the function creates the file
  53.         : CREATE_ALWAYS;//Creates a new file. 
  54.                         //If the file exists, the function overwrites the file and clears the existing attributes.
  55.     int nFlag = FILE_ATTRIBUTE_NORMAL |
  56.          FILE_FLAG_OVERLAPPED/*异步IO*//* | FILE_FLAG_WRITE_THROUGH*/ | FILE_FLAG_NO_BUFFERING;
  57.     if (INVALID_HANDLE_VALUE == 
  58.         (this->m_Handle = CreateFile(lpszFileName, GENERIC_WRITE | GENERIC_READ, 
  59.         FILE_SHARE_READ, NULL, nCreateFlag, nFlag, NULL)) 
  60.         )//文件打开失败
  61.     {
  62.         this->m_Handle = NULL;
  63.         return FALSE;
  64.     }
  65.     else
  66.     {
  67.         if (Apped) //追写
  68.         {
  69.             this->SeekToEnd();
  70.             this->m_dwOffsetLow = this->GetPosition(this->m_dwOffsetHigh);
  71.         }
  72.         
  73.         strncpy(this->m_Path, lpszFileName, MAX_PATH - 1);//store the file path
  74.         return TRUE;
  75.     }
  76. }
  77. void CBufferLog::Close( )
  78. {
  79.     if (this->m_Buffer && this->m_dwCurPos != 0)
  80.     {
  81.         LONG lCount = this->m_dwFreeLen;//冗余数据量
  82.         memset(this->m_Buffer + this->m_dwCurPos, 0, this->m_dwFreeLen);//剩余空间用0替补
  83.         
  84.         this->Write(this->m_BufferSize);//输出整个buffer内容,后面的冗余数据需要删除
  85.         
  86.         this->m_dwCurPos  = 0;//指针复位
  87.         this->m_dwFreeLen = this->m_BufferSize;
  88.         //获取实际文件位置,因为FILE_FLAG_NO_BUFFERING只能整扇区读写
  89.         if (this->m_BufferSize != this->m_dwCurPos)//后面有冗余数据
  90.         {
  91.             while (!HasOverlappedIoCompleted(m_pOverLapped))
  92.             {
  93.                 Sleep(0);
  94.             }
  95.             
  96.             //删除冗余数据
  97.             SetFilePointer(this->m_Handle, -lCount, NULL, FILE_END);//前移到冗余数据前
  98.             SetEndOfFile(this->m_Handle);
  99.         }
  100.     }
  101.     
  102.     if (this->m_Handle)
  103.     {   
  104.         while (!HasOverlappedIoCompleted(m_pOverLapped))
  105.         {
  106.             Sleep(0);
  107.         }
  108.         CloseHandle(this->m_Handle);
  109.         this->m_Handle = NULL;
  110.     }
  111. }
  112. CBufferLog::~CBufferLog()
  113. {
  114.     //关闭文件
  115.     this->Close();
  116.     if (this->m_Buffer)
  117.     {
  118.         delete []m_Buffer;
  119.         this->m_Buffer = NULL;
  120.     }
  121.     if (this->m_pOverLapped)
  122.     {
  123.         delete this->m_pOverLapped;
  124.         this->m_pOverLapped = NULL;
  125.     }
  126. }
  127. void CBufferLog::WriteLog(const void *lpBuf, DWORD dwCount)
  128. {
  129.     if (m_dwFreeLen >= dwCount)
  130.     {
  131.         memcpy(this->m_Buffer + this->m_dwCurPos, lpBuf, dwCount);
  132.         this->m_dwCurPos += dwCount;
  133.         this->m_dwFreeLen -= dwCount;
  134.     }
  135.     else//比缓冲区剩余空间大
  136.     {
  137.         DWORD dwLeft = dwCount; //剩余数量
  138.         while (dwLeft > 0)
  139.         {   
  140.             if (m_dwFreeLen >= dwLeft)//缓冲区够用
  141.             {
  142.                 memcpy(this->m_Buffer + this->m_dwCurPos, 
  143.                     (BYTE*)lpBuf + dwCount - dwLeft, dwLeft);
  144.                 this->m_dwCurPos += dwLeft;
  145.                 this->m_dwFreeLen -= dwLeft;
  146.                 dwLeft = 0;
  147.                 break;
  148.             }
  149.             else//缓冲区不够
  150.             {
  151.                 memcpy(this->m_Buffer + this->m_dwCurPos, 
  152.                     (BYTE*)lpBuf + dwCount - dwLeft, m_dwFreeLen);              
  153.                 
  154.                 this->m_dwCurPos += m_dwFreeLen;
  155.                 dwLeft -= m_dwFreeLen;  //未处理数量
  156.                 this->Flush();//缓冲区已满,输出
  157.             }
  158.         }
  159.     }
  160. }
  161. DWORD CBufferLog::GetPosition()
  162. {
  163.     this->Flush();
  164.     return SetFilePointer(this->m_Handle, 0L, NULL, FILE_CURRENT );
  165. }
  166. BOOL CBufferLog::Write(DWORD dwLen) //写缓冲区内容到磁盘
  167.     while (!HasOverlappedIoCompleted(m_pOverLapped))
  168.     {
  169.         Sleep(0);
  170.     }
  171.     m_pOverLapped->Offset     = this->m_dwOffsetLow;
  172.     m_pOverLapped->OffsetHigh = this->m_dwOffsetHigh;
  173.     if (this->m_dwOffsetLow + dwLen <= 0xFFFFFFFF)
  174.     {
  175.         this->m_dwOffsetLow += dwLen;
  176.     }
  177.     else
  178.     {
  179.         this->m_dwOffsetHigh++;//高位加1
  180.         this->m_dwOffsetLow += (dwLen - 0xFFFFFFFF);
  181.     }   
  182.     return WriteFile(this->m_Handle, this->m_Buffer, dwLen, 
  183.         &m_dwByteWrittern, m_pOverLapped);
  184. }
  185. DWORD CBufferLog::GetPosition(DWORD &High32)
  186. {
  187.     this->Flush();
  188.     High32 = 0;
  189.     return SetFilePointer(this->m_Handle, 0, (PLONG)&High32, FILE_CURRENT);
  190. }

===================================

非注明转载的文章和blog在未特殊声明情况下一般为本人原创或整理,
原创文章版权本人(lonefox)所有;转载文章版权归原作者所有;

http://blog.youkuaiyun.com/boythl

欢迎转载,但请注明出处,保留作者和版权信息。

===================================

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值