PoEdu - Windows階段班 【Po學校】Windows編程 Lesson004_003-2 文件操做
-
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上,須要徹底的重寫。
-
002_CreateFile參數詳解
- 參見下面中文翻譯
- 事務型操做:
- 把一個操做分紅「讀」「寫」「修改」「完成」4個部分,中間123任意部分失敗,則操做無效,「回滾」到操做進行以前的狀態。
- 好比程序安裝,能夠作成一個「事務型」操做,只有當總體完成,這個事務型操做,纔算真正的完成,不然「回滾」至安裝以前的狀態。
- 只有在同步時,會考慮事務型操做;當異步時,事務型操做是不適用的。
- lpFileName 文件名稱
- ANSI版本中MAX_PATH 宏 代替 260;Unicode版本中,沒有限制長度。
- dwDesiredAccess 權限:以何種權限打開文件
- 能夠多個權限疊加使用
- 如置爲0,則設備不具備讀和寫的權限。好比咱們只要訪問一文件的建立時間,不須要對文件讀和寫時,這個設置就很是的合適。
- dwShareMode 共享模式
- 一系列共享給別人的模式。
- 如置爲0,別的程序佔用了這個文件,那麼沒法再次被打開。
- 當訪問模式衝突時,有GetLastError返回ERROR_SHARING_VIOLATION
- 內核對象打開以後,須要關閉。不然此項設置的權限一直生效。
- lpSecurityAttributes 安全描述符
- 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
- 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 歷史問題,疑難問題,在出問題時查看
-
CreateFile中文翻譯:
- 函數功能
- CreateFile 函數用於建立或打開一個文件或者 I/O 設備。最常使用的 I/O 設備以下:
- 文件
- 文件流
- 文件夾
- 物理磁盤
- 邏輯磁盤驅動器
- 控制檯程序緩衝區
- 磁帶
- 通訊資源
- 郵槽
- 管道
- 此函數返回一個指向用於訪問來自不一樣類型I/O的文件或設備的句柄,其訪問權限取決於它所訪問的文件、設備和咱們所指定的標記位、屬性。
- 爲了使之能夠處理事務型 I/O,請使用 CreateFileTransacted 函數。
- 函數原型
- 參數解析
- 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
歡迎關注本站公眾號,獲取更多信息