《Windows系统编程》读后感(一)

      读了前5章,感触最深的是作者在例子程序中对UNICODE的考虑,另外就是将windowsAPIUNIX进行对比,结合前段时间在看的《UNIX网络编程 2》,感觉对比性很强。

      印象最深刻的就是第5章的3个排序示例,将外部文件排序用内存来实现,堆,内存映射文件以及基准指针的使用让人大开眼见,不过比之《windows核心编程》还是有差距
#include "EvryThng.h"

#define KEY_SIZE 8

    
/* Structure definition for a tree node. */

typedef 
struct _TreeNode {
    
struct _TreeNode *Left, *Right;
    TCHAR Key [KEY_SIZE];
    LPTSTR pData;
}
 TREENODE, *LPTNODE, **LPPTNODE;

#define NODE_SIZE sizeof (TREENODE)
#define NODE_HEAP_ISIZE 0x8000
#define DATA_HEAP_ISIZE 0x8000
#define MAX_DATA_LEN 0x1000
#define TKEY_SIZE KEY_SIZE * sizeof (TCHAR)

LPTNODE FillTree (HANDLE, HANDLE, HANDLE);
BOOL Scan (LPTNODE);
int KeyCompare (LPCTSTR, LPCTSTR); iFile; /* for access in exception handler */
BOOL InsertTree (LPPTNODE, LPTNODE);

int _tmain (int argc, LPTSTR argv [])
{
    HANDLE hIn, hNode 
= NULL, hData = NULL;
    LPTNODE pRoot;
    BOOL NoPrint;
    CHAR ErrorMessage[
256];
    
int iFirstFile = Options (argc, argv, _T ("n"), &NoPrint, NULL);

    
if (argc <= iFirstFile)
        ReportError (_T (
"Usage: sortBT [options] files"), 1, FALSE);
                    
/* Process all files on the command line. */
    
for (iFile = iFirstFile; iFile < argc; iFile++) __try {
                    
/* Open the input file. */
        hIn 
= CreateFile (argv [iFile], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
        
if (hIn == INVALID_HANDLE_VALUE)
            RaiseException (
000, NULL);
                    
/* Allocate the two heaps. */
        __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);
                    
/* Process the input file, creating the tree. */
            pRoot 
= FillTree (hIn, hNode, hData);
                    
/* Display the tree in Key order. */
            
if (!NoPrint) {
                _tprintf (_T (
"Sorted file: %s\n"), argv [iFile]);
                Scan (pRoot);
            }
 
        }
 __finally /* Heaps and file handle are always closed */
            
/* Destroy the two heaps and data structures. */
            
if (hNode != NULL) HeapDestroy (hNode);
            
if (hNode != NULL) HeapDestroy (hData);
            hNode 
= NULL; hData = NULL;
            
if (hIn != INVALID_HANDLE_VALUE) CloseHandle (hIn);
        }

    }
 /* End of main file processing loop and try block. */

    __except (EXCEPTION_EXECUTE_HANDLER) 
{
        _stprintf (ErrorMessage, _T(
"\n%s %s"), _T("sortBT error on file:"), argv[iFile]);
        ReportError (ErrorMessage, 
0, TRUE);
    }

    
return 0;
}


LPTNODE FillTree (HANDLE hIn, HANDLE hNode, HANDLE hData)

/* Scan the input file, creating a binary search tree in the
    hNode heap with data pointers to the hData heap. 
*/

/* Use the calling program's exception handler. */
{
    LPTNODE pRoot 
= NULL, pNode;
    DWORD nRead, i;
    BOOL AtCR;
    TCHAR DataHold [MAX_DATA_LEN];
    LPTSTR pString;
                    
/* Open the input file. */
    
while (TRUE) {
        pNode 
= HeapAlloc (hNode, HEAP_ZERO_MEMORY, NODE_SIZE);
        pNode
->pData = NULL;
        (pNode
->Left) = pNode->Right = NULL;
                    
/* Read the key. Return if done. */
        
if (!ReadFile (hIn, pNode->Key, TKEY_SIZE,
                
&nRead, NULL) || nRead != TKEY_SIZE)
                    
/* Assume end of file on error. */
            
return pRoot;    /* Read the data until the end of line. */
        AtCR 
= FALSE;         /* Last character was not a CR. */

        
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';

        
/* DataHold contains the data without the key.
            Combine the Key and the Data. 
*/


        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;
                
/* Insert the new node into the search tree. */
        InsertTree (
&pRoot, pNode);

    }
 /* End of while (TRUE) loop */
    
return NULL; /* Failure */
}


BOOL InsertTree (LPPTNODE ppRoot, LPTNODE pNode)

/* Insert the new node, pNode, into the binary search tree, pRoot. */
{
    
if (*ppRoot == NULL) {
        
*ppRoot = pNode;
        
return TRUE;
    }

    
if (KeyCompare (pNode->Key, (*ppRoot)->Key) < 0)
        InsertTree (
&((*ppRoot)->Left), pNode);
    
else
        InsertTree (
&((*ppRoot)->Right), pNode);
    
return TRUE;
}


int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)

/* Compare two records of generic characters.
    The key position and length are global variables. 
*/

{
    
return _tcsncmp (pKey1, pKey2, KEY_SIZE);
}


static BOOL Scan (LPTNODE pNode)

/* Scan and print the contents of a binary tree. */
{
    
if (pNode == NULL)
        
return TRUE;
    Scan (pNode
->Left);
    _tprintf (_T (
"%s\n"), pNode->pData);
    Scan (pNode
->Right);
    
return TRUE;
}


#include "EvryThng.h"

/* Definitions of the record structure in the sort file. */

#define DATALEN 56
#define KEY_SIZE 8

typedef 
struct _RECORD {
    TCHAR Key [KEY_SIZE];
    TCHAR Data [DATALEN];
}
 RECORD;

#define RECSIZE sizeof (RECORD)
typedef RECORD 
* LPRECORD;
int KeyCompare (LPCTSTR, LPCTSTR);

int _tmain (int argc, LPTSTR argv [])
{
    
/* The file is the first argument. Sorting is done in place. */
    
/* Sorting is done by file memory mapping. */

    HANDLE hFile 
= INVALID_HANDLE_VALUE, hMap = NULL;
    HANDLE hStdOut 
= GetStdHandle (STD_OUTPUT_HANDLE);
    LPVOID pFile 
= NULL;
    DWORD FsLow, Result 
= 2;
    TCHAR TempFile [MAX_PATH];
    LPTSTR pTFile;

    BOOL NoPrint;
    
int iFirstFile;

    iFirstFile 
= Options (argc, argv, _T ("n"), &NoPrint, NULL);

    
if (argc <= iFirstFile)
        ReportError (_T (
"Usage: sortFL [options] files"), 1, FALSE);

_try 
{    /* try-except */
        
/* Copy the input file to a temp output file that will be sorted.
            Do not alter the input file. 
*/


    _stprintf (TempFile, _T (
"%s%s"), argv [iFirstFile], _T (".tmp"));

    CopyFile (argv [iFirstFile], TempFile, TRUE);

    Result 
= 1;     /* tmp file is new and should be deleted. */

        
/* Open the file (use the temporary copy). */

    hFile 
= CreateFile (TempFile, GENERIC_READ
            
| GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    
if (hFile ==INVALID_HANDLE_VALUE)
        ReportException (_T (
"File open failed."), 2);

        
/* Get file size.
            If the file is too large, catch that when it is mapped. 
*/


    FsLow 
= GetFileSize (hFile, NULL);

    
if (FsLow == 0/* There is nothing to sort */
        CloseHandle (hFile);
        
return 0;    /* You might want to put out an informational message */
    }

        
/* Create a file mapping object.
            Use the file size but add space for the null character. 
*/


    hMap 
= CreateFileMapping (hFile, NULL, PAGE_READWRITE, 0, FsLow + TSIZE, NULL);
    
if (hMap == NULL)
        ReportException (_T (
"Create File map failed."), 3);

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

        
/* Now sort the file.
            Perform the sort with the C library - in mapped memory. 
*/


    qsort (pFile, FsLow 
/ RECSIZE, RECSIZE, KeyCompare);

        
/* Print out the entire sorted file. Treat it as one single string. */

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

        
/* Indicate successful completion. */

    Result 
= 0;              
    ReportException (EMPTY, 
5); /* Force an exception to clean up. */
    
return 0;
}
 /* End of inner try-except. */

_except (EXCEPTION_EXECUTE_HANDLER) 
{

    
/* Catch any exception here. Indicate any error.
        This is the normal termination. Delete the temporary
        file and Free all the resources. 
*/


    
if (pFile != NULL)
        UnmapViewOfFile (pFile);
    
if (hMap != NULL)
        CloseHandle (hMap);
    
if (hFile != INVALID_HANDLE_VALUE)
        CloseHandle (hFile);
    
if (Result != 2)
        DeleteFile (TempFile);
    
return Result;
}

}
 /* End of _tmain */

/*  CODE FROM HERE TO END IS NOT INCLUDED IN TEXT. */

int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)

/* Compare two records of generic characters.
    The key position and length are global variables. 
*/

{
    
return _tcsncmp (pKey1, pKey2, KEY_SIZE);
}



#include "EvryThng.h"

int KeyCompare (LPCTSTR, LPCTSTR);
DWORD CreateIndexFile (DWORD, LPCTSTR, LPTSTR);
DWORD_PTR KStart, KSize;    
/* Key start position & size (TCHAR). */
BOOL Revrs;

int _tmain (int argc, LPTSTR argv [])
{
    
/* The file is the first argument. Sorting is done in place. */
    
/* Sorting is done by file memory mapping. */

    HANDLE hInFile, hInMap;    
/* Input file handles. */
    HANDLE hXFile, hXMap;    
/* Index file handles. */
    HANDLE hStdOut 
= GetStdHandle (STD_OUTPUT_HANDLE);
    BOOL IdxExists, NoPrint;
    DWORD FsIn, FsX, RSize, iKey, nWrite, 
*pSizes;
    LPTSTR pInFile 
= NULL;
    LPBYTE pXFile 
= NULL, pX; 
    TCHAR _based (pInFile) 
*pIn;
    TCHAR IdxFlNam [MAX_PATH], ChNewLine 
= '\n';
    
int FlIdx;

        
/* Determine the options. */

     FlIdx 
= Options (argc, argv, _T ("rIn"), &Revrs, &IdxExists, &NoPrint, NULL);
    
if (FlIdx >= argc)
        ReportError (_T (
"No file name on command line."), 1, FALSE);

/* Step 1: Open and Map the Input File. */

    hInFile 
= CreateFile (argv [FlIdx], GENERIC_READ | GENERIC_WRITE,
            
0, NULL, OPEN_EXISTING, 0, NULL);
    
if (hInFile == INVALID_HANDLE_VALUE)
        ReportError (_T (
"Failed to open input file."), 2, TRUE);

        
/* Create a file mapping object. Use the file size. */

    hInMap 
= CreateFileMapping (hInFile, NULL, PAGE_READWRITE, 00, NULL);
    
if (hInMap == NULL)
        ReportError (_T (
"Failed to create input file mapping."), 3, TRUE);
    pInFile 
= MapViewOfFile (hInMap, FILE_MAP_ALL_ACCESS, 000);
    
if (pInFile == NULL)
        ReportError (_T (
"Failed to map input file."), 4, TRUE);

        
/* Get the file size.
            As the mapping succeeded, the file size is less than 2 GB. 
*/


    FsIn 
= GetFileSize (hInFile, NULL);

        
/* Create the index file name. */

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

/* Steps 2 and 3, if necessary. */

    
if (!IdxExists)
        RSize 
= CreateIndexFile (FsIn, IdxFlNam, pInFile);

/* Step 4. Map the index file. */

    hXFile 
= CreateFile (IdxFlNam, GENERIC_READ | GENERIC_WRITE,
            
0, NULL, OPEN_EXISTING, 0, NULL);
    
if (hXFile == INVALID_HANDLE_VALUE)
        ReportError (_T (
"Failed to open existing index file."), 5, TRUE);

        
/* Create a file mapping object. Use the file size. */

    hXMap 
= CreateFileMapping (hXFile, NULL, PAGE_READWRITE, 00, NULL);
    
if (hXMap == NULL)
        ReportError (_T (
"Failed to create index file mapping."), 6, TRUE);
    pXFile 
= MapViewOfFile (hXMap, FILE_MAP_ALL_ACCESS, 000);    
    
if (pXFile == NULL)
        ReportError (_T (
"Failed to map index file."), 7, TRUE);
    FsX 
= GetFileSize (hXFile, NULL);

    
/* Get the key size/key start and adjust the file size for the
        KeySize/KeyStart fields. Compute the record size from the key size. 
*/


    pSizes 
= (LPDWORD)pXFile; KSize = *pSizes; 
    KStart 
= *(pSizes + 1);
    FsX 
-= 2 * sizeof (DWORD); 

/* Step 5. Sort the index file using qsort. */

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

/* Step 6. Output the input file in sorted order. */

        
/* Point to the address of the input file string.
            Start in the Input file. 
*/


    pX 
= pXFile + 2 * sizeof (DWORD) + RSize - sizeof (LPTSTR);

    
if (!NoPrint)
    
for (iKey = 0; iKey < FsX / RSize; iKey++{        
        WriteFile (hStdOut, 
&ChNewLine, TSIZE, &nWrite, NULL);

            
/* The cast on pX is important, as it is a pointer to a
                byte and we need the four bytes of a based pointer. 
*/

        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. Free all the handles and maps. */

    UnmapViewOfFile (pInFile);
    CloseHandle (hInMap);
    CloseHandle (hInFile);
    UnmapViewOfFile (pXFile);
    CloseHandle (hXMap);
    CloseHandle (hXFile);
    
return 0;
}

    
DWORD CreateIndexFile (DWORD FsIn, LPCTSTR IdxFlNam, LPTSTR pInFile)

/* Perform Steps 2-3 as defined in program description. */
/* This step will be skipped if the options specify use of an existing index file. */
{
    HANDLE hXFile;
    TCHAR _based (pInFile) 
*pInScan = 0;
    DWORD nWrite;

    
/* Step 2a: Create an index file.
        Do not map it yet as its length is not known. 
*/


    hXFile 
= CreateFile (IdxFlNam, GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ, NULL, CREATE_ALWAYS, 
0, NULL);
    
if (hXFile == INVALID_HANDLE_VALUE)
        ReportError (_T (
"Failure to create index file."), 8, TRUE);
    
    
/* Step 2b: Get the first key and determine key size and start. */

    KStart 
= (DWORD_PTR) pInScan;
                
/* Computed start of key field. */
    
while (*pInScan != ' ' && *pInScan != '\t') pInScan++;
                
/* Computed end of key field */

    KSize 
= ((DWORD_PTR) pInScan - KStart) / TSIZE;

        
/* Computed key field size in characters. */

    
/* Step 2c. Step 3. Scan the complete file, writing keys
        and record pointers to the key file. 
*/

    
/* The eight bytes contain the Key Size/Key Start.
        This is necessary so that we can re-use the index file. 
*/


    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
++/* Skip to end of line. */
        }

        pInScan 
+= 2/* Skip past CR, LF. */
    }

    CloseHandle (hXFile);
            
/* Size of an individual record. */
    
return KSize * TSIZE + sizeof (LPTSTR);
}


int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)

/* Compare two records of generic characters.
    The key position and length are global variables. 
*/

{
    DWORD i;
    TCHAR t1, t2;
    
int Result = 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
++;
    }

    
return Revrs ? -Result : Result;
}

posted on 2008-06-05 20:43  Phinecos(洞庭散人)  阅读(1191)  评论(0编辑  收藏  举报

导航