1. 程式人生 > >C/C++ 檔案操作之CreateFile、ReadFile和WriteFile

C/C++ 檔案操作之CreateFile、ReadFile和WriteFile

1. CreateFile

  這個函式的功能是建立或者開啟一個檔案或者I/O裝置,通常使用的I/O形式有檔案、檔案流、目錄、物理磁碟、卷、終端流等。如執行成功,則返回檔案控制代碼。 INVALID_HANDLE_VALUE 表示出錯,會設定 GetLastError 。
  函式的宣告定義:

  HANDLE WINAPI CreateFile(
  _In_      LPCTSTR lpFileName,              
  _In_      DWORD dwDesiredAccess,
  _In_      DWORD dwShareMode,
  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_      DWORD dwCreationDisposition,
  _In_      DWORD dwFlagsAndAttributes,
  _In_opt_  HANDLE
hTemplateFile );

引數列表:

引數 型別描述
lpFileName String ,要開啟的檔案的名字
dwDesiredAccess Long ,如果為 GENERIC_READ 表示允許對裝置進行讀訪問;如果為 GENERIC_WRITE 表示允許對裝置進行寫訪問(可組合使用);如果為零,表示只允許獲取與一個裝置有關的資訊
dwShareMode Long ,零表示不共享; FILE_SHARE_READ 和 / 或 FILE_SHARE_WRITE 表示允許對檔案進行共享訪問
lpSecurityAttributes SECURITY_ATTRIBUTES ,指向一個 SECURITY_ATTRIBUTES 結構的指標,定義了檔案的安全特性(如果作業系統支援的話)
dwCreationDisposition Long ,下述常數之一:CREATE_NEW 建立檔案; 如檔案存在則會出錯CREATE_ALWAYS 建立檔案,會改寫前一個檔案;OPEN_EXISTING 檔案必須已經存在。由裝置提出要求;OPEN_ALWAYS 如檔案不存在則建立它; TRUNCATE_EXISTING 將現有檔案縮短為零長度
dwFlagsAndAttributes Long ,一個或多個下述常數:FILE_ATTRIBUTE_ARCHIVE 標記歸檔屬性;FILE_ATTRIBUTE_COMPRESSED 將檔案標記為已壓縮,或者標記為檔案在目錄中的預設壓縮方式;FILE_ATTRIBUTE_NORMAL 預設屬性; FILE_ATTRIBUTE_HIDDEN 隱藏檔案或目錄;FILE_ATTRIBUTE_READONLY 檔案為只讀;FILE_ATTRIBUTE_SYSTEM 檔案為系統檔案;FILE_FLAG_WRITE_THROUGH 作業系統不得推遲對檔案的寫操作; FILE_FLAG_OVERLAPPED 允許對檔案進行重疊操作;FILE_FLAG_NO_BUFFERING 禁止對檔案進行緩衝處理。檔案只能寫入磁碟卷的扇區塊;FILE_FLAG_RANDOM_ACCESS 針對隨機訪問對檔案緩衝進行優化; FILE_FLAG_SEQUENTIAL_SCAN 針對連續訪問對檔案緩衝進行優化 ;FILE_FLAG_DELETE_ON_CLOSE 關閉了上一次開啟的控制代碼後,將檔案刪除。特別適合臨時檔案;
hTemplateFile Long ,如果不為零,則指定一個檔案控制代碼。新檔案將從這個檔案中複製擴充套件屬性

2. ReadFile

  從檔案指標指向的位置開始將資料讀出到一個檔案中, 且支援同步和非同步操作,如果檔案開啟方式沒有指明FILE_FLAG_OVERLAPPED的話,當程式呼叫成功時,它將實際讀出檔案的位元組數儲存到lpNumberOfBytesRead指明的地址空間中。FILE_FLAG_OVERLAPPED 允許對檔案進行重疊操作。
  函式宣告定義:

  BOOL WINAPI ReadFile(
  __in          HANDLE hFile,                   // 檔案控制代碼
  __out         LPVOID lpBuffer,                // 接收資料用的 buffer
  __in          DWORD nNumberOfBytesToRead,     // 要讀取的位元組數
  __out         LPDWORD lpNumberOfBytesRead,    // 實際讀取到的位元組數
  __in          LPOVERLAPPED lpOverlapped       // OVERLAPPED 結構,一般設定為 NULL 
);

程式碼示例:

BOOL Read(char *filePath)
{
    HANDLE pFile;
    DWORD fileSize;
    char *buffer,*tmpBuf;
    DWORD dwBytesRead,dwBytesToRead,tmpLen;

    pFile = CreateFile(filePath,GENERIC_READ,          
        FILE_SHARE_READ,
        NULL,               
        OPEN_EXISTING,        //開啟已存在的檔案 
        FILE_ATTRIBUTE_NORMAL, 
        NULL);

    if ( pFile == INVALID_HANDLE_VALUE)
    {
        printf("open file error!\n");
        CloseHandle(pFile);
        return FALSE;
    }

    fileSize = GetFileSize(pFile,NULL);          //得到檔案的大小

    buffer = (char *) malloc(fileSize);
    ZeroMemory(buffer,fileSize);
    dwBytesToRead = fileSize;
    dwBytesRead = 0;
    tmpBuf = buffer;

    do{                                       //迴圈讀檔案,確保讀出完整的檔案    

        ReadFile(pFile,tmpBuf,dwBytesToRead,&dwBytesRead,NULL);

        if (dwBytesRead == 0)
            break;

        dwBytesToRead -= dwBytesRead;
        tmpBuf += dwBytesRead;

        } while (dwBytesToRead > 0);

        //  TODO 處理讀到的資料 buffer

    free(buffer);
    CloseHandle(pFile);

    return TRUE;
}

3. WriteFile

  將資料寫入一個檔案。該函式比fwrite函式要靈活的多。也可將這個函式應用於對通訊裝置、管道、套接字以及郵槽的處理。返回時,TRUE(非零)表示成功,否則返回零。會設定GetLastError。
函式宣告定義:

BOOL WINAPI WriteFile(
  __in          HANDLE hFile,                   // 檔案控制代碼
  __in          LPCVOID lpBuffer,               // 要寫入的資料
  __in          DWORD nNumberOfBytesToWrite,    // 要寫入的位元組數
  __out         LPDWORD lpNumberOfBytesWritten, // 實際寫入的位元組數
  __in          LPOVERLAPPED lpOverlapped       // OVERLAPPED 結構,一般設定為 NULL
);

程式碼示例:

BOOL Write(char *buffer, DWORD contentLen)
{
    HANDLE pFile;
    char *tmpBuf;
    DWORD dwBytesWrite,dwBytesToWrite;

    pFile = CreateFile(filePath,GENERIC_WRITE,          
        0,
        NULL,               
        CREATE_ALWAYS,        //總是建立檔案
        FILE_ATTRIBUTE_NORMAL, 
        NULL);

    if ( pFile == INVALID_HANDLE_VALUE)
    {
        printf("create file error!\n");
        CloseHandle(pFile);
        return FALSE;
    }

    dwBytesToWrite = contentLen;
    dwBytesWrite = 0;

    tmpBuf = buffer;

    do{                                       //迴圈寫檔案,確保完整的檔案被寫入  

        WriteFile(pFile,tmpBuf,dwBytesToWrite,&dwBytesWrite,NULL);

        dwBytesToWrite -= dwBytesWrite;
        tmpBuf += dwBytesWrite;

        } while (dwBytesToWrite > 0);

    CloseHandle(pFile);

    return TRUE;
}