C/C++文件API簡單操作


一、判斷文件夾/文件是否存在

  根據在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);
  若找到該目錄返回 FILE_ATTRIBUTE_DIRECTORY
  若未找到 返回FALSE.

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+" 以“寫入/更新”方式打開文件,相當於wr+疊加的效果。既可以讀取也可以寫入,也就是隨意更新文件。如果文件不存在,那么創建一個新文件;如果文件存在,那么清空文件內容(相當於刪除原文件,再創建一個新文件)。
"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 ;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM