PoEdu - Windows階段班 【Po學校】Windows編程 Lesson004_003-2 文件操作
阿新 • • 發佈:2017-06-23
環境 語言 設定 out msdn str 函數 示例 encrypt
-
001_函數的不同版本
- HANDLE : CreateFile()函數返回一個內核對象的句柄
- WINAPI : 一種調用約定,調用方式。
- _In_ 與 _In_opt_ : 本身沒有意義,一個說明宏,來標明這個參數的性質。
- _In_ 說明此參數是“輸入型”參數
- _In_Opt_ 說明此參數是“輸入指針型”參數
- _Out_ 說明此參數是“輸出型”參數
- 輸出參數要保障:輸出型參數,具有可操作的空間
- VS2015中,CreateFile()是一個宏:
WINBASEAPI HANDLE WINAPI CreateFileA(
_In_ LPCSTR lpFileName,
……
);
?
WINBASEAPI HANDLE WINAPI CreateFileW(
_In_ LPCWSTR lpFileName,
……
);
?
#ifdef UNICODE
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif // !UNICODE- windows平臺編程,關於字符的處理,需要區分兩大陣營:1 寬字符集 與 2 窄字符集
- “寬”與“窄”兩種不同的字節集,會導致類型的不同; 最初CreateFile函數支持的是窄字節,後來發現窄字節在多國語言環境中,是不夠用的,windows的設計者們,把CreateFile函數變成一個宏,這個宏使得CreateFile有了CreateFileA()與 CreateFileW()兩個版本。CreateFileA()兼容窄字節,CreateFileW()推廣寬字節。
- 實際使用過程中,造成了很多的不方便 :
- 示例1:
wchar_t *filename = L"d:\\1.txt";
CreateFile(filename,……); - 看示例代碼,此時程序員以寬字節設定 filename,但是當外部變換為“窄”字節集時,CreateFile這個宏,能變換成CreateFileW這個版本,而wchar_t * filename不能自動兼容“窄”字節。所以就出現了“TCHAR”這個宏,而右邊也出現了“TEXT()”這個宏。
- TEXT()這個宏,作用是:當環境為UNICODE時,在字符串前面加“L”;否則不加“L”。
- 以上整套處理方案,不能移植到linux上,需要完全的重寫。
- 示例1:
-
002_CreateFile參數詳解
- 參見下面中文翻譯
- 事務型操作:
- 把一個操作分成“讀”“寫”“修改”“完成”4個部分,中間123任意部分失敗,則操作無效,“回滾”到操作進行之前的狀態。
- 比如程序安裝,可以做成一個“事務型”操作,只有當整體完成,這個事務型操作,才算真正的完成,否則“回滾”至安裝之前的狀態。
- 只有在同步時,會考慮事務型操作;當異步時,事務型操作是不適用的。
- 把一個操作分成“讀”“寫”“修改”“完成”4個部分,中間123任意部分失敗,則操作無效,“回滾”到操作進行之前的狀態。
- lpFileName 文件名稱
- ANSI版本中MAX_PATH 宏 代替 260;Unicode版本中,沒有限制長度。
- dwDesiredAccess 權限:以何種權限打開文件
- 可以多個權限疊加使用
- 如置為0,則設備不具有讀和寫的權限。比如我們只要訪問一文件的創建時間,不需要對文件讀和寫時,這個設置就非常的合適。
- dwShareMode 共享模式
- 一系列共享給別人的模式。
- 如置為0,別的程序占用了這個文件,那麽無法再次被打開。
- 當訪問模式沖突時,有GetLastError返回ERROR_SHARING_VIOLATION
- 內核對象打開之後,需要關閉。否則此項設置的權限一直生效。
- lpSecurityAttributes 安全描述符
- 如置為NULL , 則無法被子進程繼承
- dwCreationDisposition 當文件存在與否時,針對存在與否,展開何種操作
- CREATE_ALWAYS 問題創建一個新文件
- 文件被重寫成功時,將last-error code設置為ERROR_ALREADY_EXISTS
- 文件不存在,創建成功時,將last-error code 設置為0。
- CREATE_NEW 僅文件不存在時,才創建一個新文件
- 如文件存在,執行失敗,將last-error code設置為ERROR_FILE_EXISTS
- OPEN_ALWAYS 總是打開一個文件
- 文件存在,執行成功,置為ERROR_ALREADY_EXISTS
- 文件不存在,路徑名合法且可寫時,創建一個新文件,last-error code置為0 。
- OPEN_EXISTING 僅在文件存在時,打開它
- 文件不存在,則置為ERROR_FILE_NOT_FOUND
- TRUNCATE_EXISTING 測試一個文件是否存在
- 僅當文件存在時,才打開一個文件並且,將其大小截取到0字節
- 文件不存在,函數執行失敗,last-error code置為ERROR_FILE_NOT_FOUND
- CREATE_ALWAYS 問題創建一個新文件
- dwFlagsAndAttributes
-
003_CreateFile完成
- dwFlagsAndAttributes 屬性與標記位
- 對於文件 FILE_ATTRIBUTE_NORMAL是最常用 默認值
- 設置文件的屬性值的組合,所有屬性值是: FILE_ATTRIBUTE_NORMAL
- FILE_FLAG_BACKUP_SEMANTICS
- 備份或者恢復
- FILE_FLAG_NO_BUFFERING
- 以無讀寫緩沖區的方式打開
- FILE_FLAG_WRITE_THROUGH
- 寫操作不通過任何中間緩沖區緩沖,直接寫回磁盤
- hTemplateFile 內核相同的對象
- 一般為NULL
- 當不為NULL時,上一參數dwFlagsAndAttributes所有設置無效,將繼承此參數,也就是新給出的內核對象,繼承此對象的所有Flags.
- 返回值
- 返回文件句柄
- 如果失敗,返回last-error code 為 INVALID_HANDLE_VALUE
- 備註 具體查看MSDN 歷史問題,疑難問題,在出問題時查看
- 打開句柄之後,要進行關閉。
- dwFlagsAndAttributes 屬性與標記位
-
CreateFile中文翻譯:
- 函數功能
- CreateFile 函數用於創建或打開一個文件或者 I/O 設備。最常使用的 I/O 設備如下:
- 文件
- 文件流
- 文件夾
- 物理磁盤
- 邏輯磁盤驅動器
- 控制臺程序緩沖區
- 磁帶
- 通信資源
- 郵槽
- 管道
- 此函數返回一個指向用於訪問來自不同類型I/O的文件或設備的句柄,其訪問權限取決於它所訪問的文件、設備和我們所指定的標記位、屬性。
- 為了使之可以處理事務型 I/O,請使用 CreateFileTransacted 函數。
- CreateFile 函數用於創建或打開一個文件或者 I/O 設備。最常使用的 I/O 設備如下:
- 函數原型
- 參數解析
- lpFileName
- 1 指定要打開、創建的文件或設備的名字。你可以在名字中使用斜杠(/)或者反斜杠(\)
- 2 在此函數的 ANSI 版本中,名字長度被限制為 MAX_PATH 個字符。為了將此限制擴展到 32767 個寬字符,需要調用此函數的 Unicode 版本,並且在添加在路徑名中添加 “\?\” 前綴。獲取更多的信息,參見 Naming Files, Paths, and Namespaces
- 3 想獲取關於特殊設備的名字,參見 Defining an MS-DOS Device Name
- 4 為了創建一個文件流,需要指定文件名,一個冒號加上流文件的名字。獲取更多信息,參見 File Streams
- dwDesiredAccess
- 指定以何種權限打開文件或設備,可以歸納為:讀訪問權、寫訪問權、讀寫訪問權、非讀非寫訪問權
- 最常使用的值為 GENERIC_READ, GENERIC_WRITE, 或者二者都用(GENERIC_READ | GENERIC_WRITE)。獲取更多信息,參見 Generic Access Rights, File Security and Access Rights, File Access Rights Constants 和 ACCESS_MASK
- 如果參數值為 0,那麽程序可以在不訪問文件或設備情況下,詢問某些元數據,如文件、目錄或者設備屬性。此外,即使 GENERIC_READ 請求,也會被拒絕
- 你無法請求一個與共享模式沖突的訪問權限。共享模式是在參數 dwShareMode 中設置的
- 獲取更多信息,參見本文備註以及 Creating and Opening Files
- dwShareMode
- 設置文件或者設備的共享模式,包括讀、寫、讀寫、刪除、全部權限或者以上什麽權限都沒有(參考下面的表格)。此參數不影響對屬性和擴展屬性的訪問請求
- 如果此參數為 0 且 CreateFile 函數執行成功,那麽此文件或設備無法被共享,且在其句柄被關閉前,無法被再次打開。更多信息,參見本文備註。
- 你無法設置一個與訪問模式相沖突的共享模式。此時如果 CreateFile 函數執行失敗,那麽 GetLastError 函數會返回 ERROR_SHARING_VIOLATION
- 為了允許進程去共享一個已經在另一個進程中打開的文件或句柄,那麽可對以下一個或多個取值進行組合,且各取值間需要可互相兼容。更多有關此參數與 dwDesiredAccess 參數的合法取值組合的信息,參見 Creating and Opening Files
- 註意:在句柄被關閉之前,每個句柄的共享選項都會一直生效,且與進程的運行上下文(process context)無關。
- lpSecurityAttributes
- 指向 SECURITY_ATTRIBUTES 結構體的指針。此結構體擁有兩個分開但是相關的數據成員:一個是可選的安全描述符,另一個是決定返回的句柄是否可以被子進程繼承的 Boolean 值
- 此參數可以設置為 NULL
- 如果參數為 NULL,那麽 CreateFile 函數返回的句柄無法被任意此進程的子進程所繼承,且與返回的句柄所對應的文件或句柄擁有一個默認的安全描述符
- 該結構體的 lpSecurityDescriptor 成員為文件或設備指定一個安全描述符(SECURITY_DESCRIPTOR)。如果此成員取值為 NULL,那麽與返回的句柄所對應的文件或句柄擁有一個默認的安全描述符
- 當打開一個已經存在的文件或設備時,CreateFile 函數忽略 lpSecurityDescriptor 成員,但是 bInheritHandle 成員仍然可以使用
- 結構體的 bInheritHandle 成員用於設置返回的句柄是否可以被繼承
- 更多信息,參見本文備註
- dwCreationDisposition
- 用於設置當文件存在或不存在時,要對文件或設備執行何種操作
- 對於設備來說,此參數通常設置為 OPEN_EXISTING
- 更多信息,參見本文備註
- 這個參數的值必須為以下值之一,且只能選擇一個而不能組合多個:
- dwFlagsAndAttributes
- 文件或設備的屬性值和標記位,對於文件來說,FILE_ATTRIBUTE_NORMAL 是最常用的默認值
- 此參數可以是任意文件屬性值(FILE_ATTRIBUTE_*)的組合。所有其他的文件屬性值會覆蓋 FILE_ATTRIBUTE_NORMAL
- 此參數也可以包含任意標記位(FILE_FLAG_*)的組合以控制文件或設備的行為、權限設置和其他目的。此外,還可以與任意 FILE_ATTRIBUTE_* 進行組合
- 這個參數還可以通過指定 SECURITY_SQOS_PRESENT 標記來包含 Security Quality of Service (SQOS) 信息。與SQOS相關的標記位信息見屬性與標記位表格下面的表格中
- 註意:當CreateFile 打開一個已存在的文件時,它通常將文件屬性和文件標記位組合在一起,並且忽略在 dwFlagsAndAttributes 中定義的屬性值。詳細例子見 Creating and Opening Files
- 以下的屬性和標記位可能只適用於文件的打開,而並非支持所有其他 CreateFile 函數可以打開的設備。想了解更多信息,參見本文備註部分和 Creating and Opening Files。想進一步了解文件屬性相關信息,參見 SetFileAttributes 函數。你還可以在 File Attribute Constants 中看到完整的介紹所有文件屬性的值和對應描述信息
- hTemplateFile
- 指向一個擁有 GENERIC_READ 訪問權限的的模板文件的合法句柄
- 此模板文件為即將創建的文件提供屬性和擴展屬性
- 參數值可以為 NULL
- 如果打開一個已存在的文件,則 CreateFile 函數忽略這個參數
- 如果打開一個新的被加密文件,此函數從其父目錄中繼承自由存取控制列表。更多信息,見 File Encryption
- lpFileName
- 函數功能
PoEdu - Windows階段班 【Po學校】Windows編程 Lesson004_003-2 文件操作