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);
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 ;