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

#define
KEY_SIZE8


/**/
/*Structuredefinitionforatreenode.*/


typedef
struct
_TreeNode
{
struct_TreeNode*Left,*Right;
TCHARKey[KEY_SIZE];
LPTSTRpData;
}
TREENODE,
*
LPTNODE,
**
LPPTNODE;

#define
NODE_SIZEsizeof(TREENODE)
#define
NODE_HEAP_ISIZE0x8000
#define
DATA_HEAP_ISIZE0x8000
#define
MAX_DATA_LEN0x1000
#define
TKEY_SIZEKEY_SIZE*sizeof(TCHAR)

LPTNODEFillTree(HANDLE,HANDLE,HANDLE);
BOOLScan(LPTNODE);

int
KeyCompare(LPCTSTR,LPCTSTR);iFile;
/**/
/*foraccessinexceptionhandler*/
BOOLInsertTree(LPPTNODE,LPTNODE);

int
_tmain(
int
argc,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;
}

int
KeyCompare(LPCTSTRpKey1,LPCTSTRpKey2)


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

{
return_tcsncmp(pKey1,pKey2,KEY_SIZE);
}

static
BOOLScan(LPTNODEpNode)


/**/
/*Scanandprintthecontentsofabinarytree.*/

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


/**/
/*Definitionsoftherecordstructureinthesortfile.*/

#define
DATALEN56
#define
KEY_SIZE8


typedef
struct
_RECORD
{
TCHARKey[KEY_SIZE];
TCHARData[DATALEN];
}
RECORD;

#define
RECSIZEsizeof(RECORD)
typedefRECORD
*
LPRECORD;
int
KeyCompare(LPCTSTR,LPCTSTR);

int
_tmain(
int
argc,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.*/

int
KeyCompare(LPCTSTRpKey1,LPCTSTRpKey2)


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

{
return_tcsncmp(pKey1,pKey2,KEY_SIZE);
}

#include
"
EvryThng.h
"

int
KeyCompare(LPCTSTR,LPCTSTR);
DWORDCreateIndexFile(DWORD,LPCTSTR,LPTSTR);

DWORD_PTRKStart,KSize;
/**/
/*Keystartposition&size(TCHAR).*/
BOOLRevrs;

int
_tmain(
int
argc,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);
}

int
KeyCompare(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;
}