006 異步IO操作
# 異步IO操作
CreateFile 使用
VS2015 新建win32 控制臺應用程序 WindowsFileDemo
win32控制臺寫窗口程序
需要加入頭文件 #include <fileAPI.h> 就可以來使用CreateFile
分別有 CreateFileA CreateFileW 窄字節 寬字節
1 HANDLE WINAPI CreateFile( 2 _In_ LPCTSTR lpFileName, 3 _In_ DWORD dwDesiredAccess, 4 _In_ DWORD dwShareMode,5 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, 6 _In_ DWORD dwCreationDisposition, 7 _In_ DWORD dwFlagsAndAttributes, 8 _In_opt_ HANDLE hTemplateFile 9 );
//第一個參數 LPCTSTR lpFileName 文件名
//第二個參數 DWORD dwDesiredAccess 訪問權限
GENERIC_ALL 所有權限 需要管理員權限 否則可能打開失敗
GENERIC_EXECUTE 文件是否存在
GENERIC_READ 讀
GENERIC_WRITE 寫
GENERIC_READ | GENERIC_WRITE 組合
//第三個參數 DWORD dwShareMode 打開後是否共享 不需要共享的話就寫入0
0
FILE_SHARE_DELETE
FILE_SHARE_READ
FILE_SHARE_WRITE
//第四個參數 lpSecurityAttributes 一般填寫nullpte
用來設定一個指向包含兩個不同但相關的數據成員:一個可選的安全描述符和一個布爾值來決定是否由子進程返回的句柄可以被繼承。
//第五個參數 DWORD dwCreationDisposition 打開方式
CREATE_NEW 創建文件;如文件存在則會出錯
CREATE_ALWAYS 創建文件,會改寫前一個文件
OPEN_EXISTING 文件必須已經存在。由設備提出要求
OPEN_ALWAYS 如文件不存在則創建它
TRUNCATE_EXISTING 將現有文件縮短為零長度
//第六個參數 dwFlagsAndAttributesLong, 一個或多個下述常數
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 關閉了上一次打開的句柄後,將文件刪除。特別適合臨時文件
也可在Windows NT下組合使用下述常數標記:
SECURITY_ANONYMOUS,
SECURITY_IDENTIFICATION,
SECURITY_IMPERSONATION,
SECURITY_DELEGATION,
SECURITY_CONTEXT_TRACKING,
SECURITY_EFFECTIVE_ONLY
//第七個參數 HANDLE hTemplateFile
hTemplateFile,hTemplateFile為一個文件或設備句柄,表示按這個參數給出的句柄為模板創建文件(就是將該句柄文件拷貝到lpFileName指定的路徑,然後再打開)。
它將指定該文件的屬性擴展到新創建的文件上面,這個參數可用於將某個新文件的屬性設置成與現有文件一樣,並且這樣會忽略dwAttrsAndFlags。
通常這個參數設置為NULL,為空表示不使用模板,一般為空。
返回值
如執行成功,則返回文件句柄。
INVALID_HANDLE_VALUE表示出錯,會設置GetLastError。
即使函數成功,但若文件存在,且指定了CREATE_ALWAYS 或 OPEN_ALWAYS,GetLastError也會設為ERROR_ALREADY_EXISTS
FormatMessage 函數
● FormatMessage是一個Windows API函數。它的功能就是將GetLastError函數得到的錯誤信息(這個錯誤信息是數字代號)轉化成字符串信息的函數。
DWORD WINAPI FormatMessage (
DWORD dwFlags, // source and processing options
LPCVOID lpSource, // message source
DWORD dwMessageId, // message identifier
DWORD dwLanguageId, // language identifier
LPTSTR lpBuffer, // message buffer
DWORD nSize, // maximum size of message buffer
va_list *Arguments // array of message inserts
);
○ dwFlags
標誌位,決定如何說明lpSource參數,dwFlags的低位制定如何處理換行功能在輸出緩沖區,也決定最大寬度的格式化輸出行。[1]
○ lpSource
根據dwFlags標誌而定
○ dwMessageId
請求的消息的標識符。當dwFlags標誌為FORMAT_MESSAGE_FROM_STRING時會被忽略。[1]
○ dwLanguageId
請求的消息的語言標識符。
○ LPTSTR lpBuffer
接收錯誤信息描述的緩沖區指針。
○ nSize
如果FORMAT_MESSAGE_ALLOCATE_BUFFER標誌沒有被指定,這個參數必須指定為輸出緩沖區的大小,如果指定,這個參數指定為分配給輸出緩沖區的最小數。[1]
○ Arguments
保存格式化信息中的插入值的一個數組。
LocalFree 函數
○ 功能:釋放局部內存對象並使句柄失效
● hMem:局部內存對象的句柄,通過函數LocalAlloc或LocalReAlloc返回的。
○ 返回值
● 函數執行成功返回NULL,否則返回內存對象的句柄,要獲得詳細錯誤信息,調用GetLastError函數。
在Windows系統中, 文件大小分為以下兩種:
物理大小
GetFileSize 已棄用, 因為對於小文件還可以, 但是大文件會超過輸出參數的範圍
DWORD WINAPI GetFileSize(
_In_ HANDLE hFile, //文件句柄
_Out_opt_ LPDWORD lpFileSizeHigh //文件大小 輸出參數
);
GetFileSizeEx
占用大小
BOOL WINAPI GetFileSizeEx(
_In_ HANDLE hFile, //文件句柄
_Out_ PLARGE_INTEGER lpFileSize //文件大小 輸出參數
ReadFile
BOOL ReadFile(
HANDLE hFile, //文件的句柄
LPVOID lpBuffer, //用於保存讀入數據的一個緩沖區
DWORD nNumberOfBytesToRead, //要讀入的字節數
LPDWORD lpNumberOfBytesRead, //指向實際讀取字節數的指針
LPOVERLAPPED lpOverlapped //結構體指針
//如文件打開時指定了FILE_FLAG_OVERLAPPED,那麽必須,用這個參數引用一個特殊的結構。
//該結構定義了一次異步讀取操作。否則,應將這個參數設為NULL
);
返回值: 成功返回非0
同步下, 如果返回值不等於0.
異步下, 參數5(lpOverlapped)不為NULL時, 當讀到文件結尾時, 返回值為FALSE, GetLastError為ERROR_HANDLE_EOF.
WriteFile
BOOL WriteFile(
HANDLE hFile, //文件句柄
LPCVOID lpBuffer, //數據緩存區指針
DWORD nNumberOfBytesToWrite, //你要寫的字節數
LPDWORD lpNumberOfBytesWritten, //用於保存實際寫入字節數的存儲區域的指針
LPOVERLAPPED lpOverlapped//OVERLAPPED //結構體指針
);
返回值:
成功返回非0的值
1 #define UNICODE 2 #include <tchar.h> 3 #include <wchar.h> 4 #include <windows.h> 5 #include <exception> 6 7 class WindowsException:public std::exception 8 { 9 public: 10 WindowsException(DWORD dwErrorCode):m_dwErrorCode(dwErrorCode) 11 { 12 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 13 nullptr, 14 m_dwErrorCode, 15 0, 16 reinterpret_cast<LPWSTR>(&m_strErrorMsg), 17 0, 18 nullptr); 19 } 20 ~WindowsException() 21 { 22 LocalFree(m_strErrorMsg); 23 } 24 const TCHAR* what() const 25 { 26 return m_strErrorMsg; 27 } 28 private: 29 DWORD m_dwErrorCode; 30 TCHAR * m_strErrorMsg; 31 }; 32 33 class MyFile 34 { 35 public: 36 MyFile( const TCHAR *strFilePath ):m_hFile(INVALID_HANDLE_VALUE) //構造函數 37 { 38 SetPath(strFilePath); 39 } 40 41 ~MyFile() //析構函數 42 { 43 if( m_hFile != INVALID_HANDLE_VALUE) 44 { 45 CloseHandle(m_hFile); 46 } 47 } 48 BOOL OpenFileW( _In_ DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE, //讀寫權限 49 _In_ DWORD dwShareMode = FILE_SHARE_READ, //共享讀文件操作 50 _In_ DWORD dwCreationDisposition = OPEN_ALWAYS, //如文件不存在則創建它 51 _In_ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, //默認屬性 52 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL, 53 _In_opt_ HANDLE hTemplateFile = NULL) 54 { 55 BOOL bRet = TRUE; 56 m_hFile = CreateFileW( m_strFilePath, //接收傳遞過來的參數 57 dwDesiredAccess, 58 dwShareMode, 59 lpSecurityAttributes, 60 dwCreationDisposition, 61 dwFlagsAndAttributes, 62 hTemplateFile); 63 if( m_hFile == INVALID_HANDLE_VALUE) //不等於說明打開成功 相等的話說明成功 64 { 65 bRet = FALSE; 66 throw WindowsException(GetLastError()); 67 } 68 return bRet; 69 } 70 VOID SetPath( const TCHAR *strFilePath) 71 { 72 SIZE_T nstrLen = _tcslen(strFilePath) + sizeof(TCHAR); 73 m_strFilePath = new TCHAR(nstrLen); 74 _tcscpy_s(m_strFilePath, nstrLen, strFilePath); 75 } 76 const TCHAR *GetPath() const 77 { 78 return m_strFilePath; 79 } 80 private: 81 HANDLE m_hFile; 82 TCHAR *m_strFilePath; 83 84 }; 85 86 int main() 87 { 88 try 89 { 90 MyFile clsFile; 91 clsFile.SetPath( TEXT("demo.txt")); 92 clsFile.OpenFile(); 93 } 94 catch(WindowsException &exception) 95 { 96 MessageBoxW(nullptr, exception.what(), exception.what(), MB_OK); 97 } 98 99 /* 100 HANDLE hFile = CreateFileW( L"Demo.txt", //文件名稱 101 GENERIC_READ | GENERIC_WRITE, //文件的訪問權限 102 0, //文件共享 103 nullptr, 104 OPEN_EXISTING, //文件必須已經存在。方式 105 FILE_ATTRIBUTE_NORMAL, //默認屬性 106 nullptr); //為空表示不使用模板,一般為空 107 if( hFile == INVALID_HANDLE_VALUE) //如果存在的話彈出對話框 108 //INVALID_HANDLE_VALUE = -1 文件無法打開 109 //彈出對話框 110 { 111 MessageBox( nullptr, L"Error", L"Error", MB_OK ); 112 } 113 114 CloseHandle(hFile); //關閉句柄 115 116 */ 117 return 0; 118 }
006 異步IO操作