• Testing for the End of a File (Windows 的异步 IO)


    The ReadFile function checks for the end-of-file condition (EOF) differently for synchronous and asynchronous read operations. When a synchronous read operation gets to the end of a file, ReadFile returns TRUE and sets the variable pointed to by the lpNumberOfBytesRead parameter to zero. An asynchronous read operation can encounter the end of a file during the initiating call to ReadFile or during subsequent asynchronous operations if the file pointer is programmatically advanced beyond the end of the file.

    The following C++ example shows how to test for the end of a file during a synchronous read operation.

    C++
      // Attempt a synchronous read operation.
      bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL);
    
      // Check for eof.
      if (bResult &&  nBytesRead == 0) 
       {
        // at the end of the file
       }
    

    The test for end-of-file during an asynchronous read operation is slightly more involved than for a similar synchronous read operation. The end-of-file indicator for asynchronous read operations is when GetOverlappedResult returns FALSE and GetLastError returns ERROR_HANDLE_EOF.

    The following C++ example shows how to test for the end of file during an asynchronous read operation.

    C++
    #include <windows.h>
    #include <tchar.h>
    #include <stdio.h>
    
    #define BUF_SIZE (61)
    
    LPCTSTR ErrorMessage( DWORD error ) 
    
    // Routine Description:
    //      Retrieve the system error message for the last-error code
    { 
    
        LPVOID lpMsgBuf;
    
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            error,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf,
            0, NULL );
    
        return((LPCTSTR)lpMsgBuf);
    }
    
    void GoDoSomethingElse(void)
    
    // Routine Description:
    //     Placeholder to demo when async I/O might want to do
    //     other processing.
    {
        printf("Inside GoDoSomethingElse()
    ");
    }
    
    DWORD AsyncTestForEnd( HANDLE hEvent, HANDLE hFile )
    
    // Routine Description:
    //      Demonstrate async ReadFile operations that can catch
    //      End-of-file conditions. Unless the operation completes
    //      synchronously or the file size happens to be an exact
    //      multiple of BUF_SIZE, this routine will eventually force
    //      an EOF condition on any file.
    
    // Parameters:
    //      hEvent - pre-made manual-reset event.
    //
    //      hFile - pre-opened file handle, overlapped.
    //
    //      inBuffer - the buffer to read in the data to.
    //
    //      nBytesToRead - how much to read (usually the buffer size).
    
    // Return Value:
    //      Number of bytes read.
    {
        char inBuffer[BUF_SIZE];
        DWORD nBytesToRead      = BUF_SIZE;
        DWORD dwBytesRead       = 0;
        DWORD dwFileSize        = GetFileSize(hFile, NULL);
        OVERLAPPED stOverlapped = {0};
    
        DWORD dwError  = 0;
        LPCTSTR errMsg = NULL;
    
        BOOL bResult   = FALSE;
        BOOL bContinue = TRUE;
    
        // Set up overlapped structure event. Other members are already 
        // initialized to zero.
        stOverlapped.hEvent = hEvent; 
    
        // This is an intentionally brute-force loop to force the EOF trigger.
        // A properly designed loop for this simple file read would use the
        // GetFileSize API to regulate execution. However, the purpose here
        // is to demonstrate how to trigger the EOF error and handle it.
    
        while(bContinue)
        {
            // Default to ending the loop.
            bContinue = FALSE;
            
            // Attempt an asynchronous read operation.
            bResult = ReadFile(hFile,
                               inBuffer,
                               nBytesToRead,
                               &dwBytesRead,
                               &stOverlapped); 
         
            dwError = GetLastError();
    
            // Check for a problem or pending operation. 
            if (!bResult) 
            { 
                switch (dwError) 
                { 
                     
                    case ERROR_HANDLE_EOF:
                    {
                        printf("
    ReadFile returned FALSE and EOF condition, async EOF not triggered.
    ");
                        break;
                    }
                    case ERROR_IO_PENDING: 
                    { 
                        BOOL bPending=TRUE;
    
                        // Loop until the I/O is complete, that is: the overlapped 
                        // event is signaled.
    
                        while( bPending )
                        {
                            bPending = FALSE;
                            
                            // Pending asynchronous I/O, do something else
                            // and re-check overlapped structure.
                            printf("
    ReadFile operation is pending
    ");
         
                            // Do something else then come back to check. 
                            GoDoSomethingElse(); 
         
                            // Check the result of the asynchronous read
                            // without waiting (forth parameter FALSE). 
                            bResult = GetOverlappedResult(hFile,
                                                          &stOverlapped,
                                                          &dwBytesRead,
                                                          FALSE) ; 
         
                            if (!bResult) 
                            { 
                                switch (dwError = GetLastError()) 
                                { 
                                    case ERROR_HANDLE_EOF: 
                                    { 
                                        // Handle an end of file
                                        printf("GetOverlappedResult found EOF
    ");
                                        break;
                                    } 
    
                                    case ERROR_IO_INCOMPLETE:
                                    {
                                        // Operation is still pending, allow while loop
                                        // to loop again after printing a little progress.
                                        printf("GetOverlappedResult I/O Incomplete
    ");
                                        bPending = TRUE;
                                        bContinue = TRUE;
                                        break;
                                    }
    
                                    default:
                                    {
                                        // Decode any other errors codes.
                                        errMsg = ErrorMessage(dwError);
                                        _tprintf(TEXT("GetOverlappedResult failed (%d): %s
    "), 
                                            dwError, errMsg);
                                        LocalFree((LPVOID)errMsg);
                                    }
                                }
                            } 
                            else
                            {
                                printf("ReadFile operation completed
    ");
    
                                // Manual-reset event should be reset since it is now signaled.
                                ResetEvent(stOverlapped.hEvent);
                            }
                        }
                        break;
                    }
    
                    default:
                    {
                        // Decode any other errors codes.
                        errMsg = ErrorMessage(dwError);
                        printf("ReadFile GLE unhandled (%d): %s
    ", dwError, errMsg); 
                        LocalFree((LPVOID)errMsg);
                        break;
                    }
                }
            }
            else
            {
                // EOF demo did not trigger for the given file.
                // Note that system caching may cause this condition on most files
                // after the first read. CreateFile can be called using the
                // FILE_FLAG_NOBUFFERING parameter but it would require reads are
                // always aligned to the volume's sector boundary. This is beyond
                // the scope of this example. See comments in the main() function.
    
                printf("ReadFile completed synchronously
    ");
            }
    
            // The following operation assumes the file is not extremely large, otherwise 
            // logic would need to be included to adequately account for very large
            // files and manipulate the OffsetHigh member of the OVERLAPPED structure.
    
            stOverlapped.Offset += dwBytesRead;
            if ( stOverlapped.Offset < dwFileSize )             
                bContinue = TRUE;
        }
    
        return stOverlapped.Offset;
    }
    
    void __cdecl _tmain(int argc, TCHAR *argv[])
    
    // To force an EOF condition, execute this application specifying a
    // zero-length file. This is because the offset (file pointer) must be
    // at or beyond the end-of-file marker when ReadFile is called. For
    // more information, see the comments for the AsyncTestForEnd routine.
    
    {
        HANDLE hEvent;
        HANDLE hFile;
        DWORD dwReturnValue;
    
        printf("
    ");
        if( argc != 2 )
        {
            printf("ERROR:	Incorrect number of arguments
    
    ");
            printf("%s <file_name>
    ", argv[0]);
            return;
        }
    
        hFile = CreateFile(argv[1],                // file to open
                           GENERIC_READ,           // open for reading
                           FILE_SHARE_READ,        // share for reading
                           NULL,                   // default security
                           OPEN_EXISTING,          // existing file only
                           FILE_FLAG_OVERLAPPED,   // overlapped operation
                           NULL);                  // no attr. template
     
        if (hFile == INVALID_HANDLE_VALUE) 
        { 
            DWORD dwError = GetLastError();
            LPCTSTR errMsg = ErrorMessage(dwError);
            printf("Could not open file (%d): %s
    ", dwError, errMsg); 
            LocalFree((LPVOID)errMsg);
            return; 
        }
    
        hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    
        if (hEvent == NULL) 
        { 
            DWORD dwError = GetLastError();
            LPCTSTR errMsg = ErrorMessage(dwError);
            printf("Could not CreateEvent: %d %s
    ", dwError, errMsg); 
            LocalFree((LPVOID)errMsg);
            return; 
        }
    
        dwReturnValue = AsyncTestForEnd(hEvent, hFile);
    
        printf( "
    Read complete. Bytes read: %d
    ", dwReturnValue);
    
        CloseHandle(hFile);
        CloseHandle(hEvent);
    }
    

    The output from this sample code is as follows.

    syntax
    ReadFile operation is pending
    Inside GoDoSomethingElse()
    GetOverlappedResult I/O Incomplete
    
    ReadFile operation is pending
    Inside GoDoSomethingElse()
    ReadFile operation completed
    
    Complete. Bytes read: 541
    
  • 相关阅读:
    二次离线莫队
    一些不等积分的练习(持续更新)
    杂题20210427
    杂题20210415
    杂题20210203
    php pack()函数详解与示例
    SHOI2020抱灵祭
    BJOI2021游记+题解
    博客搬家
    听课记录 210220【分治,树分治,CDQ分治】
  • 原文地址:https://www.cnblogs.com/liujx2019/p/11692473.html
Copyright © 2020-2023  润新知