读了前5章,感触最深的是作者在例子程序中对UNICODE的考虑,另外就是将windows的API和UNIX进行对比,结合前段时间在看的《UNIX网络编程 卷2》,感觉对比性很强。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
印象最深刻的就是第5章的3个排序示例,将外部文件排序用内存来实现,堆,内存映射文件以及基准指针的使用让人大开眼见,不过比之《windows核心编程》还是有差距
#include"EvryThng.h"
#defineKEY_SIZE8

/**//*Structuredefinitionforatreenode.*/

typedefstruct_TreeNode
{
struct_TreeNode*Left,*Right;
TCHARKey[KEY_SIZE];
LPTSTRpData;
}TREENODE,*LPTNODE,**LPPTNODE;
#defineNODE_SIZEsizeof(TREENODE)
#defineNODE_HEAP_ISIZE0x8000
#defineDATA_HEAP_ISIZE0x8000
#defineMAX_DATA_LEN0x1000
#defineTKEY_SIZEKEY_SIZE*sizeof(TCHAR)
LPTNODEFillTree(HANDLE,HANDLE,HANDLE);
BOOLScan(LPTNODE);
intKeyCompare(LPCTSTR,LPCTSTR);iFile;/**//*foraccessinexceptionhandler*/
BOOLInsertTree(LPPTNODE,LPTNODE);
int_tmain(intargc,LPTSTRargv[])

{
HANDLEhIn,hNode=NULL,hData=NULL;
LPTNODEpRoot;
BOOLNoPrint;
CHARErrorMessage[256];
intiFirstFile=Options(argc,argv,_T("n"),&NoPrint,NULL);
if(argc<=iFirstFile)
ReportError(_T("Usage:sortBT[options]files"),1,FALSE);
/**//*Processallfilesonthecommandline.*/
for(iFile=iFirstFile;iFile<argc;iFile++)__try
{
/**//*Opentheinputfile.*/
hIn=CreateFile(argv[iFile],GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
if(hIn==INVALID_HANDLE_VALUE)
RaiseException(0,0,0,NULL);
/**//*Allocatethetwoheaps.*/
__try
{
hNode=HeapCreate(
HEAP_GENERATE_EXCEPTIONS|HEAP_NO_SERIALIZE,NODE_HEAP_ISIZE,0);
hData=HeapCreate(
HEAP_GENERATE_EXCEPTIONS|HEAP_NO_SERIALIZE,DATA_HEAP_ISIZE,0);
/**//*Processtheinputfile,creatingthetree.*/
pRoot=FillTree(hIn,hNode,hData);
/**//*DisplaythetreeinKeyorder.*/
if(!NoPrint)
{
_tprintf(_T("Sortedfile:%s/n"),argv[iFile]);
Scan(pRoot);
}
}__finally
{/**//*Heapsandfilehandlearealwaysclosed*/
/**//*Destroythetwoheapsanddatastructures.*/
if(hNode!=NULL)HeapDestroy(hNode);
if(hNode!=NULL)HeapDestroy(hData);
hNode=NULL;hData=NULL;
if(hIn!=INVALID_HANDLE_VALUE)CloseHandle(hIn);
}
}/**//*Endofmainfileprocessingloopandtryblock.*/

__except(EXCEPTION_EXECUTE_HANDLER)
{
_stprintf(ErrorMessage,_T("/n%s%s"),_T("sortBTerroronfile:"),argv[iFile]);
ReportError(ErrorMessage,0,TRUE);
}
return0;
}
LPTNODEFillTree(HANDLEhIn,HANDLEhNode,HANDLEhData)

/**//*Scantheinputfile,creatingabinarysearchtreeinthe
hNodeheapwithdatapointerstothehDataheap.*/
/**//*Usethecallingprogram'sexceptionhandler.*/

{
LPTNODEpRoot=NULL,pNode;
DWORDnRead,i;
BOOLAtCR;
TCHARDataHold[MAX_DATA_LEN];
LPTSTRpString;
/**//*Opentheinputfile.*/
while(TRUE)
{
pNode=HeapAlloc(hNode,HEAP_ZERO_MEMORY,NODE_SIZE);
pNode->pData=NULL;
(pNode->Left)=pNode->Right=NULL;
/**//*Readthekey.Returnifdone.*/
if(!ReadFile(hIn,pNode->Key,TKEY_SIZE,
&nRead,NULL)||nRead!=TKEY_SIZE)
/**//*Assumeendoffileonerror.*/
returnpRoot;/**//*Readthedatauntiltheendofline.*/
AtCR=FALSE;/**//*LastcharacterwasnotaCR.*/

for(i=0;i<MAX_DATA_LEN;i++)
{
ReadFile(hIn,&DataHold[i],TSIZE,&nRead,NULL);
if(AtCR&&DataHold[i]==LF)break;
AtCR=(DataHold[i]==CR);
}
DataHold[i-1]='/0';

/**//*DataHoldcontainsthedatawithoutthekey.
CombinetheKeyandtheData.*/
pString=HeapAlloc(hData,HEAP_ZERO_MEMORY,
(SIZE_T)(KEY_SIZE+_tcslen(DataHold)+1)*TSIZE);
memcpy(pString,pNode->Key,TKEY_SIZE);
pString[KEY_SIZE]='/0';
_tcscat(pString,DataHold);
pNode->pData=pString;
/**//*Insertthenewnodeintothesearchtree.*/
InsertTree(&pRoot,pNode);

}/**//*Endofwhile(TRUE)loop*/
returnNULL;/**//*Failure*/
}
BOOLInsertTree(LPPTNODEppRoot,LPTNODEpNode)

/**//*Insertthenewnode,pNode,intothebinarysearchtree,pRoot.*/

{
if(*ppRoot==NULL)
{
*ppRoot=pNode;
returnTRUE;
}
if(KeyCompare(pNode->Key,(*ppRoot)->Key)<0)
InsertTree(&((*ppRoot)->Left),pNode);
else
InsertTree(&((*ppRoot)->Right),pNode);
returnTRUE;
}
intKeyCompare(LPCTSTRpKey1,LPCTSTRpKey2)

/**//*Comparetworecordsofgenericcharacters.
Thekeypositionandlengthareglobalvariables.*/

{
return_tcsncmp(pKey1,pKey2,KEY_SIZE);
}
staticBOOLScan(LPTNODEpNode)

/**//*Scanandprintthecontentsofabinarytree.*/

{
if(pNode==NULL)
returnTRUE;
Scan(pNode->Left);
_tprintf(_T("%s/n"),pNode->pData);
Scan(pNode->Right);
returnTRUE;
}
#include"EvryThng.h"

/**//*Definitionsoftherecordstructureinthesortfile.*/
#defineDATALEN56
#defineKEY_SIZE8

typedefstruct_RECORD
{
TCHARKey[KEY_SIZE];
TCHARData[DATALEN];
}RECORD;
#defineRECSIZEsizeof(RECORD)
typedefRECORD*LPRECORD;
intKeyCompare(LPCTSTR,LPCTSTR);
int_tmain(intargc,LPTSTRargv[])

{
/**//*Thefileisthefirstargument.Sortingisdoneinplace.*/
/**//*Sortingisdonebyfilememorymapping.*/
HANDLEhFile=INVALID_HANDLE_VALUE,hMap=NULL;
HANDLEhStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
LPVOIDpFile=NULL;
DWORDFsLow,Result=2;
TCHARTempFile[MAX_PATH];
LPTSTRpTFile;
BOOLNoPrint;
intiFirstFile;
iFirstFile=Options(argc,argv,_T("n"),&NoPrint,NULL);
if(argc<=iFirstFile)
ReportError(_T("Usage:sortFL[options]files"),1,FALSE);

_try
{/**//*try-except*/
/**//*Copytheinputfiletoatempoutputfilethatwillbesorted.
Donotaltertheinputfile.*/
_stprintf(TempFile,_T("%s%s"),argv[iFirstFile],_T(".tmp"));
CopyFile(argv[iFirstFile],TempFile,TRUE);

Result=1;/**//*tmpfileisnewandshouldbedeleted.*/

/**//*Openthefile(usethetemporarycopy).*/
hFile=CreateFile(TempFile,GENERIC_READ
|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if(hFile==INVALID_HANDLE_VALUE)
ReportException(_T("Fileopenfailed."),2);

/**//*Getfilesize.
Ifthefileistoolarge,catchthatwhenitismapped.*/
FsLow=GetFileSize(hFile,NULL);

if(FsLow==0)
{/**//*Thereisnothingtosort*/
CloseHandle(hFile);
return0;/**//*Youmightwanttoputoutaninformationalmessage*/
}
/**//*Createafilemappingobject.
Usethefilesizebutaddspaceforthenullcharacter.*/
hMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,FsLow+TSIZE,NULL);
if(hMap==NULL)
ReportException(_T("CreateFilemapfailed."),3);

pFile=MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0/**//*FsLow+TSIZE*/,0);
if(pFile==NULL)
ReportException(_T("MapViewfailed"),4);

/**//*Nowsortthefile.
PerformthesortwiththeClibrary-inmappedmemory.*/
qsort(pFile,FsLow/RECSIZE,RECSIZE,KeyCompare);

/**//*Printouttheentiresortedfile.Treatitasonesinglestring.*/
pTFile=(LPTSTR)pFile;
pTFile[FsLow/TSIZE]='/0';
if(!NoPrint)
PrintMsg(hStdOut,pFile);

/**//*Indicatesuccessfulcompletion.*/
Result=0;
ReportException(EMPTY,5);/**//*Forceanexceptiontocleanup.*/
return0;
}/**//*Endofinnertry-except.*/

_except(EXCEPTION_EXECUTE_HANDLER)
{

/**//*Catchanyexceptionhere.Indicateanyerror.
Thisisthenormaltermination.Deletethetemporary
fileandFreealltheresources.*/
if(pFile!=NULL)
UnmapViewOfFile(pFile);
if(hMap!=NULL)
CloseHandle(hMap);
if(hFile!=INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if(Result!=2)
DeleteFile(TempFile);
returnResult;
}
}/**//*Endof_tmain*/

/**//*CODEFROMHERETOENDISNOTINCLUDEDINTEXT.*/
intKeyCompare(LPCTSTRpKey1,LPCTSTRpKey2)

/**//*Comparetworecordsofgenericcharacters.
Thekeypositionandlengthareglobalvariables.*/

{
return_tcsncmp(pKey1,pKey2,KEY_SIZE);
}
#include"EvryThng.h"
intKeyCompare(LPCTSTR,LPCTSTR);
DWORDCreateIndexFile(DWORD,LPCTSTR,LPTSTR);
DWORD_PTRKStart,KSize;/**//*Keystartposition&size(TCHAR).*/
BOOLRevrs;
int_tmain(intargc,LPTSTRargv[])

{
/**//*Thefileisthefirstargument.Sortingisdoneinplace.*/
/**//*Sortingisdonebyfilememorymapping.*/

HANDLEhInFile,hInMap;/**//*Inputfilehandles.*/
HANDLEhXFile,hXMap;/**//*Indexfilehandles.*/
HANDLEhStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
BOOLIdxExists,NoPrint;
DWORDFsIn,FsX,RSize,iKey,nWrite,*pSizes;
LPTSTRpInFile=NULL;
LPBYTEpXFile=NULL,pX;
TCHAR_based(pInFile)*pIn;
TCHARIdxFlNam[MAX_PATH],ChNewLine='/n';
intFlIdx;

/**//*Determinetheoptions.*/
FlIdx=Options(argc,argv,_T("rIn"),&Revrs,&IdxExists,&NoPrint,NULL);
if(FlIdx>=argc)
ReportError(_T("Nofilenameoncommandline."),1,FALSE);

/**//*Step1:OpenandMaptheInputFile.*/
hInFile=CreateFile(argv[FlIdx],GENERIC_READ|GENERIC_WRITE,
0,NULL,OPEN_EXISTING,0,NULL);
if(hInFile==INVALID_HANDLE_VALUE)
ReportError(_T("Failedtoopeninputfile."),2,TRUE);

/**//*Createafilemappingobject.Usethefilesize.*/
hInMap=CreateFileMapping(hInFile,NULL,PAGE_READWRITE,0,0,NULL);
if(hInMap==NULL)
ReportError(_T("Failedtocreateinputfilemapping."),3,TRUE);
pInFile=MapViewOfFile(hInMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pInFile==NULL)
ReportError(_T("Failedtomapinputfile."),4,TRUE);

/**//*Getthefilesize.
Asthemappingsucceeded,thefilesizeislessthan2GB.*/
FsIn=GetFileSize(hInFile,NULL);

/**//*Createtheindexfilename.*/
_stprintf(IdxFlNam,_T("%s%s"),argv[FlIdx],_T(".idx"));

/**//*Steps2and3,ifnecessary.*/
if(!IdxExists)
RSize=CreateIndexFile(FsIn,IdxFlNam,pInFile);

/**//*Step4.Maptheindexfile.*/
hXFile=CreateFile(IdxFlNam,GENERIC_READ|GENERIC_WRITE,
0,NULL,OPEN_EXISTING,0,NULL);
if(hXFile==INVALID_HANDLE_VALUE)
ReportError(_T("Failedtoopenexistingindexfile."),5,TRUE);

/**//*Createafilemappingobject.Usethefilesize.*/
hXMap=CreateFileMapping(hXFile,NULL,PAGE_READWRITE,0,0,NULL);
if(hXMap==NULL)
ReportError(_T("Failedtocreateindexfilemapping."),6,TRUE);
pXFile=MapViewOfFile(hXMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pXFile==NULL)
ReportError(_T("Failedtomapindexfile."),7,TRUE);
FsX=GetFileSize(hXFile,NULL);

/**//*Getthekeysize/keystartandadjustthefilesizeforthe
KeySize/KeyStartfields.Computetherecordsizefromthekeysize.*/
pSizes=(LPDWORD)pXFile;KSize=*pSizes;
KStart=*(pSizes+1);
FsX-=2*sizeof(DWORD);

/**//*Step5.Sorttheindexfileusingqsort.*/
if(!IdxExists)
qsort(pXFile+2*sizeof(DWORD),FsX/RSize,RSize,KeyCompare);

/**//*Step6.Outputtheinputfileinsortedorder.*/

/**//*Pointtotheaddressoftheinputfilestring.
StartintheInputfile.*/
pX=pXFile+2*sizeof(DWORD)+RSize-sizeof(LPTSTR);
if(!NoPrint)
for(iKey=0;iKey<FsX/RSize;iKey++)
{
WriteFile(hStdOut,&ChNewLine,TSIZE,&nWrite,NULL);

/**//*ThecastonpXisimportant,asitisapointertoa
byteandweneedthefourbytesofabasedpointer.*/
pIn=(TCHAR_based(pInFile)*)*(DWORD_PTR*)pX;

while((*pIn!=CR||*(pIn+1)!=LF)&&(SIZE_T)pIn<(SIZE_T)FsIn)
{
WriteFile(hStdOut,pIn,TSIZE,&nWrite,NULL);
pIn++;
}
pX+=RSize;
}

/**//*Done.Freeallthehandlesandmaps.*/
UnmapViewOfFile(pInFile);
CloseHandle(hInMap);
CloseHandle(hInFile);
UnmapViewOfFile(pXFile);
CloseHandle(hXMap);
CloseHandle(hXFile);
return0;
}
DWORDCreateIndexFile(DWORDFsIn,LPCTSTRIdxFlNam,LPTSTRpInFile)

/**//*PerformSteps2-3asdefinedinprogramdescription.*/
/**//*Thisstepwillbeskippediftheoptionsspecifyuseofanexistingindexfile.*/

{
HANDLEhXFile;
TCHAR_based(pInFile)*pInScan=0;
DWORDnWrite;

/**//*Step2a:Createanindexfile.
Donotmapityetasitslengthisnotknown.*/
hXFile=CreateFile(IdxFlNam,GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL);
if(hXFile==INVALID_HANDLE_VALUE)
ReportError(_T("Failuretocreateindexfile."),8,TRUE);

/**//*Step2b:Getthefirstkeyanddeterminekeysizeandstart.*/
KStart=(DWORD_PTR)pInScan;
/**//*Computedstartofkeyfield.*/
while(*pInScan!=''&&*pInScan!='/t')pInScan++;
/**//*Computedendofkeyfield*/
KSize=((DWORD_PTR)pInScan-KStart)/TSIZE;

/**//*Computedkeyfieldsizeincharacters.*/

/**//*Step2c.Step3.Scanthecompletefile,writingkeys
andrecordpointerstothekeyfile.*/
/**//*TheeightbytescontaintheKeySize/KeyStart.
Thisisnecessarysothatwecanre-usetheindexfile.*/
WriteFile(hXFile,&KSize,sizeof(DWORD),&nWrite,NULL);
WriteFile(hXFile,&KStart,sizeof(DWORD),&nWrite,NULL);
pInScan=/**//*(TCHAR_based(pInFile)*)*/0;
while((DWORD_PTR)pInScan<FsIn)
{
WriteFile(hXFile,pInScan+KStart,KSize*TSIZE,&nWrite,NULL);
WriteFile(hXFile,&pInScan,sizeof(LPTSTR),&nWrite,NULL);
while((DWORD)(DWORD_PTR)pInScan<FsIn&&((*pInScan!=CR)
||(*(pInScan+1)!=LF)))
{
pInScan++;/**//*Skiptoendofline.*/
}
pInScan+=2;/**//*SkippastCR,LF.*/
}
CloseHandle(hXFile);
/**//*Sizeofanindividualrecord.*/
returnKSize*TSIZE+sizeof(LPTSTR);
}
intKeyCompare(LPCTSTRpKey1,LPCTSTRpKey2)

/**//*Comparetworecordsofgenericcharacters.
Thekeypositionandlengthareglobalvariables.*/

{
DWORDi;
TCHARt1,t2;
intResult=0;
for(i=0;i<KSize&&Result==0;i++)
{
t1=*pKey1;
t2=*pKey2;
if(t1<t2)
Result=-1;
if(t1>t2)
Result=+1;
pKey1++;
pKey2++;
}
returnRevrs?-Result:Result;
}
本文深入探讨了一个基于Windows的文件排序程序,该程序利用内存映射文件技术和二叉搜索树等数据结构来高效地对外部文件进行排序。文章通过具体实例展示了如何在Windows环境下实现高效的文件排序,并与UNIX的方法进行了对比。
5万+

被折叠的 条评论
为什么被折叠?



