一、判斷文件夾/文件是否存在
根據在Windows的便捷程度排序列出一下方法,參考C/C++ 中判斷某一文件或目錄是否存在。
1. C語言函數庫_access
頭 文 件 | #include<io.h> |
函 數 名 | access/_access |
功 能 | 判斷 文件/文件夾 的訪問權限 |
用 法 | int access(const char *filename, int amode); |path=文件路徑, |mode=讀寫屬性0, 1, 2, 4, 6 --------------------------------------------------------- 0-僅存在 1-檢查文件是否可運行 2-Write-only 4-Read-only 6-Read & Write --------------------------------------------------------- 0 如果文件是指定的mode -1 如果出錯 |
這個接口適應性可能是最強,需要注意的是對於操作系統來說,文件和文件夾本質上都是文件。_waccess是_access的寬字符版本,_waccess的參數path為寬字符的字符串,其他與_access相同。
沒有下划線的位不符合ISO c++ 標准的寫法,標准要求帶下划線的標准,沒有下划線的是為了兼容以前的版本。比如在vs里你可以看到下面這樣的宏用於警告你
C/C++ code?12#define _CRT_NONSTDC_DEPRECATE(_NewName) _CRT_DEPRECATE_TEXT("The POSIX name for this item is……,所以用的話 最好用帶下划線的了。
2. Windows API函數
1)使用FindFirstFile函數
函數原型如下,但其主要功能為用FindFirstFile和FindNextFile函數歷遍指定目錄的所有文件。
1 HANDLE FindFirstFile( LPCTSTR lpFileName, // pointer to name of file to search for 2 LPWIN32_FIND_DATA lpFindFileData // pointer to returned information 3 );
如要判斷文件夾是否存在,應增加 FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY 。
1 WIN32_FIND_DATA _FIND_DATA; 2 HANDLE hFind = FindFirstFile(pDefaultDir, &_FIND_DATA); 3 if (! ((hFind == INVALID_HANDLE_VALUE) && (_FIND_DATA.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) ) { 4 if (0 != mkdir(pDefaultDir)) //CreateDirectory(szPath, SecAttri) 5 { 6 //_PRINTERROR("Create PLC DATA DIR ERROR!"); 7 } 8 } 9 FindClose(hFind);
2)使用GetFileAttributes函數
主要功能為一個指定的文件或目錄返回文件系統的屬性(可以使用GetFileAttributesEx 函數獲得更多的屬性信息。如果要實現交互式操作,可以使用GetFileAttributesTransacted 函數)。函數原型如下。
如果函數成功,返回值包含文件或目錄的屬性(屬性列表見備注)。
如果函數失敗,返回值是INVALID_FILE_ATTRIBUTES。
在判斷路徑是否為文件夾路徑的返回值應使用FILE_ATTRIBUTE_DIRECTORY。
#include<fileapi.h>
1 DWORD GetFileAttributes(LPCTSTR lpFileName //pointer to the name of a file or directory
2 );
函數返回值 | 含 義 |
FILE_ATTRIBUTE_ARCHIVE | 標示一個文件(或目錄)是一個存檔文件(或目錄)。 |
FILE_ATTRIBUTE_COMPRESSED |
標示一個文件(或目錄)是一個壓縮文件(或目錄)。
用於文件時:該文件中所有的記錄都是經過壓縮的;
用於目錄時:在該目錄下新建文件或子目錄時會默認進行壓縮。
|
FILE_ATTRIBUTE_DEVICE | 未使用。 |
FILE_ATTRIBUTE_DIRECTORY | 此句柄被視為一個目錄 |
FILE_ATTRIBUTE_ENCRYPTED |
標示一個文件(或目錄)是一個加密文件(或目錄)。
用於文件時:該文件中所有的記錄都是經過加密的,包括讀寫操作;
用於目錄時:在該目錄下新建文件或子目錄時會默認進行加密。
|
FILE_ATTRIBUTE_HIDDEN | 標示一個文件(或目錄)是一個隱藏文件(或目錄)。 |
FILE_ATTRIBUTE_NORMAL | 標示一個文件(或目錄)不具有其他屬性,此屬性只能單獨使用! |
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | 標示一個文件不可被內容索引服務索引。 |
FILE_ATTRIBUTE_OFFLINE |
標示一個文件是脫機文件,該文件中的內容無法直接使用。
如果某個文件具有該屬性,請不要輕易修改此屬性,它可能是某些遠程存儲服務程序的存儲文件。
|
FILE_ATTRIBUTE_READONLY |
標示一個文件(或目錄)是一個
只讀文件(或目錄)。
用於文件時:只能讀取文件內容,無法修改或刪除;
用於目錄時:該目錄無法刪除。
|
FILE_ATTRIBUTE_REPARSE_POINT | 標示一個文件(或目錄)擁有相關的重新解析點,比如用mklink創建的硬鏈接(hardLink)或符號鏈接(symbolic link) |
FILE_ATTRIBUTE_SPARSE_FILE | 標示一個文件是稀疏文件。 |
FILE_ATTRIBUTE_SYSTEM | 標示一個文件(或目錄)是一個系統文件(或目錄)。 |
FILE_ATTRIBUTE_TEMPORARY | 標示一個文件是臨時文件。 |
FILE_ATTRIBUTE_VIRTUAL |
標示一個文件是系統文件。
|
1 //判斷傳入路徑是文件還是文件夾 2 DWORD dwAttr = GetFileAttributes(pszFilePath); 3 bool bDir = dwAttr & FILE_ATTRIBUTE_DIRECTORY; 4 //bDir==TRUE為目錄,FALSE為文件
其中 “ 只讀 ” 、 “ 隱藏 ” 、 “ 系統 ” 、 “ 存檔 ” 為文件的四種基本屬性。 compressed , content_indexed , encrypted 只存在於 NTFS 分區中。文件去掉全部屬性后(四種基本屬性),將自動標記為 normal 。同時具有 system 和 hidden 屬性的文件會在系統中徹底隱形,這也是病毒常用的伎倆。commpressed 和 encrypted 不能共存。默認情況下文件都有 content_indexed 屬性。
3)使用函數 PathFileExists()、PathIsDirectory
() >
Shell Lightweight Utility API
-----專門判斷文件和目錄是否存在的函數。 Header: Declared in Shlwapi.h Import Library: Shlwapi.lib 以上的各種方法供參考,函數具體用法需參見MSDN
#include<Shlwapi.h> #pragma comment(lib, "shlwapi.lib") //判斷文件/文件夾是否存在 const char* pPath = "D:\\DIR\\"; BOOL bExist = PathIsDirectory(buffer);
-----該函數可以檢測文件或目錄是否存在 BOOL PathIsDirectory(LPCTSTR pszPath);
4. 使用boost庫中filesystem::exists函數
1 #include <boost/filesystem/operations.hpp>
2 #include <boost/filesystem/path.hpp>
3 #include <boost/filesystem/convenience.hpp>
4
5 using namespace boost::filesystem;
6
7 int GetFilePath(std::string &strFilePath) 8 { 9 string strPath; 10 int nRes = 0; 11 //指定路徑 12 strPath = "C:\"; 13 14 path full_path( initial_path() ); 15 full_path = system_complete( path(strPath, native ) ); 16 //判斷各級子目錄是否存在,不存在則需要創建 17 if ( !exists( full_path ) ) 18 { 19 bool bRet = create_directories(full_path); 20 if (false == bRet) 21 { 22 return -1; 23 } 24 } 25 strFilePath = full_path.native_directory_string(); 26 return 0; 27 }
二、創建文件/文件夾(可自帶判斷)
1. _mkdir / mkdir創建(access和mkdir組合)
c++中,<io.h>中的_access可以判斷文件是否存在,<direct.h>中的_mkdir可以創建文件。
#include <io.h> #include <direct.h> #include <string> //建單級目錄下------'\\' 或者 '/'等效 std::string prefix = "G:/test/"; if (_access(prefix.c_str(), 0) == -1) //如果文件夾不存在 _mkdir(prefix.c_str()); //則創建
2. 使用fopen函數
用fopen直接操作,FILE是一個文件信息結構體,附不同權限相關操作模式符號。
1 #include<stdio.h> 2 3 FILE *file = fopen(".//FileManege//F//F.dat","rb"); 4 if(file == NULL) 5 file=fopen(".//FileManege//F//F.dat","ab+"); // 先判斷有無文件,沒的話新建一個
控制讀寫權限的字符串(必須指明) | |
---|---|
打開方式 | 說 明 |
"r" | 以“只讀”方式打開文件。只允許讀取,不允許寫入。文件必須存在,否則打開失敗。 |
"w" | 以“寫入”方式打開文件。如果文件不存在,那么創建一個新文件;如果文件存在,那么清空文件內容(相當於刪除原文件,再創建一個新文件)。 |
"a" | 以“追加”方式打開文件。如果文件不存在,那么創建一個新文件;如果文件存在,那么將寫入的數據追加到文件的末尾(文件原有的內容保留)。 |
"r+" | 以“讀寫”方式打開文件。既可以讀取也可以寫入,也就是隨意更新文件。文件必須存在,否則打開失敗。 |
"w+" | 以“寫入/更新”方式打開文件,相當於w 和r+ 疊加的效果。既可以讀取也可以寫入,也就是隨意更新文件。如果文件不存在,那么創建一個新文件;如果文件存在,那么清空文件內容(相當於刪除原文件,再創建一個新文件)。 |
"a+" | 以“追加/更新”方式打開文件,相當於a和r+疊加的效果。既可以讀取也可以寫入,也就是隨意更新文件。如果文件不存在,那么創建一個新文件;如果文件存在,那么將寫入的數據追加到文件的末尾(文件原有的內容保留)。 |
控制讀寫方式的字符串(可以不寫) | |
打開方式 | 說 明 |
"t" | 文本文件。如果不寫,默認為"t" 。 |
"b" | 二進制文件。 |
注意:調用 fopen() 函數時必須指明讀寫權限,但是可以不指明讀寫方式(此時默認為"t"
)。文件正常關閉時,fclose() 的返回值為0,如果返回非零值則表示有錯誤發生。
1)使用fgets讀取文件
1 //循環讀取文件的每一行數據 2 while( fgets(str, N, fp) != NULL ) { 3 printf("%s", str); 4 }
2)使用fwrite寫入文件
1 /*返回值:返回實際寫入的數據塊數目 2 *(1)buffer:是一個指針,對fwrite來說,是要獲取數據的地址; 3 *(2)size:要寫入內容的單字節數; 4 *(3)count:要進行寫入size字節的數據項的個數; 5 *(4)stream:目標文件指針; 6 *(5)返回實際寫入的數據項個數count。 7 */ 8 size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
說明:寫入到文件的哪里? 這個與文件的打開模式有關,如果是w+,則是從file pointer指向的地址開始寫,替換掉之后的內容,文件的長度可以不變,stream的位置移動count個數;如果是a+,則從文件的末尾開始添加,文件長度加大。
fseek對此函數有作用,但是fwrite函數寫到用戶空間緩沖區,並未同步到文件中,所以修改后要將內存與文件同步可以用fflush(FILE *fp)函數同步。
3. 使用CreateFile和CreateDirectory函數
1)CreateFile接口
功能是創建或者打開一個文件或者I/O設備,通常使用的I/O形式有文件、文件流、目錄、物理磁盤、卷、終端流等。如執行成功,則返回文件句柄。 INVALID_HANDLE_VALUE 表示出錯,會設置 GetLastError 。C/C++ 文件設備操作之CreateFile、ReadFile和WriteFile。
1 HANDLE CreateFile(LPCTSTR lpFileName, //普通文件名或者設備文件名 2 DWORD dwDesiredAccess, //訪問模式(寫/讀) 3 DWORD dwShareMode, //共享模式 4 LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全屬性的指針 5 DWORD dwCreationDisposition, //如何創建 6 DWORD dwFlagsAndAttributes, //文件屬性 7 HANDLE hTemplateFile //用於復制文件句柄 8 );
2)CreateDirectory接口
CreateDirectory這個函數的作用是創建一個新的目錄。如果底層文件系統支持文件和目錄上的安全描述,該功能可將指定的安全描述到新的目錄。
如用CreateDirectory(".//FileManege",NULL);
如果文件夾FileManege不存在,則創建。
#include "shlwapi.h"
#pragma comment(lib,"shlwapi.lib")
1 /* 非0表示成功,0表示失敗。若想獲得更多的錯誤信息,調用GetLastError函數。 2 * pPathName:長指針,指向一個空結束的字符串,該字符串指定要創建的目錄的路徑。有一個默認的字符串大小限制為MAX_PATH字符的路徑。此限制是關系到這個函數是如何解析路徑。字符串的長度不超過MAX_PATH。 3 * lpSecurityAttributes:忽略,一般設置為NULL。 4 */ 5 BOOL CreateDirectory( 6 LPCTSTR lpPathName, 7 LPSECURITY_ATTRIBUTES lpSecurityAttributes 8 );
注意:這個函數不是遞歸的。它可以在一個路徑中創建唯一的最終目錄。也就是說,如果父目錄或中間目錄不存在,該函數將失敗並顯示錯誤消息ERROR_PATH_NOT_FOUND。該函數只能創建一級目錄,當根目錄或者中間目錄不存在時,該函數將不起作用。所以假如我們要創建二級以上目錄時,應該分開來一步步創建。
三、Copy / Move 文件或文件夾
CopyFile(A, B, FALSE);表示將文件A拷貝到B,如果B已經存在則覆蓋(第三參數為TRUE時表示不覆蓋), MoveFile(A, B);表示將文件A移動到B。這兩個函數都返回一個bool型變量,表示執行成功與否,當目標位置路徑不存在時,會return 0
1 #if defined(_M_CEE) 2 #undef CopyFile 3 __inline 4 BOOL 5 CopyFile( 6 LPCTSTR lpExistingFileName, 7 LPCTSTR lpNewFileName, 8 BOOL bFailIfExists 9 ) 10 { 11 #ifdef UNICODE 12 return CopyFileW( 13 #else 14 return CopyFileA( 15 #endif 16 lpExistingFileName, 17 lpNewFileName, 18 bFailIfExists 19 ); 20 } 21 #endif /* _M_CEE */
1 #if defined(_M_CEE) 2 #undef MoveFile 3 __inline 4 BOOL 5 MoveFile( 6 LPCTSTR lpExistingFileName, 7 LPCTSTR lpNewFileName 8 ) 9 { 10 #ifdef UNICODE 11 return MoveFileW( 12 #else 13 return MoveFileA( 14 #endif 15 lpExistingFileName, 16 lpNewFileName 17 ); 18 } 19 #endif /* _M_CEE */
示例代碼
1 #include <fstream> 2 #include <windows.h> 3 4 int main() 5 { 6 char *fn = "test.txt"; 7 8 std::ofstream out(fn); 9 if (!out.is_open()) 10 return 0; 11 out.close(); 12 13 WCHAR buf[256]; 14 memset(buf, 0, sizeof(buf)); 15 MultiByteToWideChar(CP_ACP, 0, fn, strlen(fn) + 1, buf, sizeof(buf) / sizeof(buf[0])); 16 CopyFile(buf, L"../file/output.txt", FALSE);//FALSE:如果目標位置已經存在同名文件,就覆蓋,return 1 17 //TRUE:如果目標位置已經存在同名文件,則補拷貝,return 0 18 //后者路徑若不錯在,return 0 19 system("pause"); 20 return 1; 21 } 22 ////////////////////////////////////////////////////////// 23 #include <fstream> 24 #include <windows.h> 25 26 int main() 27 { 28 char *fn = "test.txt"; 29 30 std::ofstream out(fn); 31 if (!out.is_open()) 32 return 0; 33 out.close(); 34 35 WCHAR buf[256]; 36 memset(buf, 0, sizeof(buf)); 37 MultiByteToWideChar(CP_ACP, 0, fn, strlen(fn) + 1, buf, sizeof(buf) / sizeof(buf[0])); 38 MoveFile(buf, L"../file/output.txt");//FALSE:將前者移動到后者中(后者路徑若不錯在,return 0) 39 40 system("pause"); 41 return 1; 42 }
--Continue ;