这里参考了 代码行数统计(修复版) http://download.csdn.net/detail/jokers_i/4939098 , 但有一点小bug.. 这里修正了再贴出来.作为自己学习笔记.. 感谢原作者..
这里建立控制台演示下代码.
代码如下:
#include <iostream>
#include <Winsock2.h> // for
#include <Windows.h>
#include <string>
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
struct CodeFileLineInfo{
DWORD codeline;
DWORD blankline;
LPTSTR filename;
CodeFileLineInfo():codeline(0),blankline(0),filename(NULL){}
VOID Reset(){codeline=blankline=0;}
};
CONST WORD Utf_8_header = 0xBBEF;
CONST WORD Uc_littte_header = 0xFEFF;
CONST WORD Uc_big_header = 0xFFFE;
inline BOOL IsVisibleChar(WORD c)
{
CONST WORD uvc[]={' ','\r','\n','\t'};
for (DWORD i=0;i<sizeof(uvc)/sizeof(uvc[0]);i++)
{
if (c==uvc[i])
{
return FALSE;
}
}
return TRUE;
}
template<class T>
VOID CalcLines(CONST T* buffer,CONST T seprator,CONST DWORD nchars,CodeFileLineInfo& cfi)
{
DWORD visible = 0;
for (DWORD i = 0;i<nchars;i++)
{
visible += IsVisibleChar(buffer[i]);
if (buffer[i] == seprator)
{
if (visible==0)
{
++cfi.blankline;
}
else
{
++cfi.codeline;
}
visible = 0;
}
}
if (buffer[nchars-1]!=seprator)
{
++cfi.codeline;
}
else if (buffer[nchars - 1] == T(10)) // 加入这个判断,如果最后一行是空行的话.也应该计算进去
{
++cfi.blankline;
}
}
VOID NumbericCodeLine(LPCTSTR filePath, CodeFileLineInfo& codeFileInfo)
{
HANDLE codefile = CreateFile(filePath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (codefile==INVALID_HANDLE_VALUE)
{
//AfxMessageBox(_T("打开文件失败"));
return;
}
BY_HANDLE_FILE_INFORMATION bhfif;
GetFileInformationByHandle(codefile,&bhfif);
if (bhfif.nFileSizeLow==0) // 这里只判断文件大小的低位的是否为0,因为高位的不为0,也是文件相当大的了 --- benben 补注
{
return;
}
LPVOID buffer=VirtualAlloc(NULL,bhfif.nFileSizeLow,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
if (!buffer)
{
// AfxMessageBox(_T("alloc memory failed!"));
return;
}
ReadFile(codefile,buffer,bhfif.nFileSizeLow,&bhfif.nFileSizeHigh,NULL);
CloseHandle(codefile);
WCHAR * wcBuffer = (WCHAR *)buffer;
DWORD nchars = 0;
if (wcBuffer[0]==Uc_littte_header||wcBuffer[0]==Uc_big_header)
{
nchars = (bhfif.nFileSizeLow-2)/2;
//处理Unicode with littel or big endian file
WCHAR NEWLINE=0x000A;
if (wcBuffer[0]==Uc_big_header)
{
for (DWORD i=0;i<nchars+1;i++)
{
wcBuffer[i] = ntohs(wcBuffer[i]);
}
}
//skip the header word
wcBuffer = wcBuffer+1;
CalcLines(wcBuffer,NEWLINE,nchars,codeFileInfo);
}
else if (wcBuffer[0]==Utf_8_header)
{
//Utf-8 encode file
CalcLines((CHAR*)buffer+3,'\n',bhfif.nFileSizeLow-3,codeFileInfo);
}
else
{
//ANSI encode file
CalcLines((CHAR*)buffer,'\n',bhfif.nFileSizeLow,codeFileInfo);
}
VirtualFree(buffer,bhfif.nFileSizeLow,MEM_RELEASE);
}
int main()
{
CodeFileLineInfo LineInfo;
std::string fileName("c:\\test\\console_study.cpp");
NumbericCodeLine(fileName.c_str(), LineInfo);
cout << fileName.c_str() << endl;
cout << "NonBlankLine = " << LineInfo.codeline << endl;
cout << "BlankLine = " << LineInfo.blankline << endl;
cout << "总行数: " << (LineInfo.codeline + LineInfo.blankline) << endl;
return 0;
}