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 ;

posted @ 2020-03-03 22:30  傍风无意  阅读(2780)  评论(0编辑  收藏  举报