本文有大量链接引用.如触犯了您的利益请下方留言
前言
熟悉的文件打开操作有open、fopen、createfile、CFile类
他们的关系(论坛上出现过的问题):CFile 或者 C++的fstrem或者C lib fopen,终究都会调用Win32 APICreateFile
CreateFile是操作系统提供的,Open由C++提供,内部也是调用CreateFile;他们在功能上没有什么区别;
windows中open依赖于CreateFile,但两者的返回值不是同一个东西,open返回的是一个数组的索引,CreateFile返回值是句柄表的多级索引
fopen与CreateFile比较(网文):
在 win7 x64 下,即使把 ACL 关闭,对一个肯定存在的文件(用 _access 检查也是存在),用 CreateFile 打开时,无论采用什么参数,都返回无效句柄 INVALID_HANDLE_VALUE。用 GetLastError 得到的错误竟然是:文件不存在,或者路径不存在!这应该是与 ACL 相关的一个问题,google了很久,也只是发现有人提出这个问题,但都没有解决该问题。无奈之下,只好抛弃微软,重用标准库的 fopen。因为标准库的 fopen 不会做 os 做的安全相关事情,所以轻松打开了文件。 同样,在写文件时,CreateFile 依然无奈,fopen轻松胜任。 随着 Android、iOS 越来越流行,代码的跨平台性就要求越高。对安全性要求不高的应用程序,弃用平台相关的 API,改用平台无关的标准库,显然是个明智之举。
但是在windows32环境下做开发,对于windows提供的api还是有必要了解的
windows api文件手册函数:点击打开链接 点击打开链接
正文
由于本人对文件操作仅限于创建、读、写等基础操作,这里仅给出基础api
一、创建、打开文件createfile (createfile的详细信息点击打开链接)
HANDLE CreateFile(
①LPCSTR lpFileName, //指向文件名的指针或filename对象路径名(LPCSTR的详细解释 点击打开链接)
②DWORD dwDesiredAccess, //访问模式 (DWORD 的详细解释点击打开链接)
③DWORD dwShareMode, //共享模式 (关于共享模式:点击打开链接)
④LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
⑤DWORD dwCreationDisposition, //创建方式
⑥DWORD dwFlagsAndAttributes, //文件属性
⑦HANDLE hTemplateFile //用于复制文件句柄 (关于该参数点击打开链接)
);
①lpFileName 文件名或路径
②dwDesiredAccess 访问模式
0 不希望从设备读取数据或向设备写入数据。如果只想改变设备的配置(如:修改文件的时间戳),可以传0
GENERIC_READ 允许对设备进行只读访问
GENERIC_WRITE 允许对设备进行只写访问,该选项并没有隐含 GENERIC_READ标志
③dwShareMode 共享模式
0 要求独占对设备的访问。如果设备已经打开,CreateFile 调用会失败;如果成功地打开了设备,后续的 CreateFile 调用会失败
FILE_SHARE_READ 如果有其他对象要用该设备,我们要求它们不得修改设备的数据;如果设备已经以写入方式或独占方式打开,那么CreateFile调用会失败
FILE_SHARE_WRITE 如果有其他内核对象要使用该设备,则要求它们不得读取设备的数据
FILE_SHARE_DELETE 当对文件进行操作的时候,我们不关心文件是否被逻辑删除或移动。在Windows内部,系统会先将文件标记为待删除,然后当该文件所有已打开的句柄都被关闭的时候,再将其真正的删除
④lpSecurityAttributes 指向安全属性的指针
指向一个SECURITY_ATTRIBUTES结构指针,定义了文件安全特性
⑤dwCreationDisposition 创建方式
CREATE_NEW 创建一个新文件,如果同名文件已经存在,那么 CreateFile调用会失败
CREATE_ALWAYS 无论同名是否存在都创建新文件,若文件存在,则覆盖
OPEN_EXISTING 打开一个已有的文件或设备,如果文件或设备不存在,那么CreateFile调用会失败
OPEN_ALWAYS 打开一个已有的文件,如果文件存在,那么CreateFile会直接打开文件,如果不存在,则会创建一个新文件
TRUNCATE_EXISTING 打开一个已有的文件并将文件大小截断为0字节,如果文件不存在,那么CreateFile调用会失败
⑥dwFlagsAndAttributes 文件属性
通信标志–缓存
FILE_FLAG_NO_BUFFERING 该标志表示在访问文件的时候不要使用任何数据缓存
FILE_FLAG_SEQUENTIAL_SCAN 指定系统顺序地访问文件,系统从文件读取的数据量会超过我们的要求(减少硬盘访问),指定了FILE_FLAG_NO_BUFFERING标志,该标志不生效
FILE_FLAG_RANDOM_ACCESS 该标志表示系统不要提前读取文件数据(指定FILE_FLAG_NO_BUFFERING,则该标志不生效)
FILE_FLAG_WRITE_THROUGH 禁止写入文件时,将数据缓存在内存中(减少数据丢失的可能性)
通信标志–其他标志
FILE_FLAG_DELETE_ON_CLOSE 文件所有的句柄都被关闭后,删除该文件
FILE_FLAG_BACKUP_SEMANTICS 用于备份和恢复软件。在打开或创建任何文件之前,为了确保视图打开文件或创建文件的进程具有所需的访问特权
FILE_FLAG_POSIX_SEMANTICS 让CreateFile在创建文件或打开文件时,以区分大小写的方式来查找文件名
FILE_FLAG_OPEN_REPARSE_POINT 告诉系统忽略文件的重解析属性(重解析属性允许一个文件系统过滤器对打开文件、读取文件、写入文件以及关闭文件这些行为进行修改)
FILE_FLAG_OPEN_NO_RECALL 该标志告诉系统不要将文件内容刚从脱机存储器(offline storage,比如磁带)恢复到联机存储器(即online storage, 如硬盘)
FILE_FLAG_OVERLAPPED 该标志告诉系统我们想以异步方式来访问设备
文件设置
FILE_ATTRIBUTE_ARCHIVE 应用程序用该标志来将文件标记为待备份或待删除。当CreateFile创建一个新文件时,会自动设置该标志
FILE_ATTRIBUTE_ENCRYPTED 文件是经过加密的
FILE_ATTRIBUTE_HIDDEN 文件是隐藏的。它不会出现在通常的目录清单中
FILE_ATTRIBUTE_NORMAL 文件没有其他属性。只有单独使用的时候,这个标志才有效(默认属性)
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 内容索引服务(content indexing service)不会对文件进行索引
FILE_ATTRIBUTE_OFFLINE 文件虽然存在,但文件内容已经被转移到脱机存储中
FILE_ATTRIBUTE_READONLY 文件只读
FILE_ATTRIBUTE_SYSTEM 文件是操作系统的一部分,专供操作系统使用
FILE_ATTRIBUTE_TEMPORARY 文件数据只会使用一小段时间。为了将访问时间降至最低,会尽量将文件数据保存在内存中
一般创建文件只要设置 FILE_ATTRIBUTE_NORMAL(默认属性)
⑦hTemplateFile 用于复制文件句柄
指向用于存储的文件句柄,!=0则指定一个文件句柄,新的文件将从这个文件中复制扩展属性,如果该函数调用成功,返回文件句柄,否则返回INVALID_HANDLE_VALUE
调用示例
以只读方式打开已存在的文件
HANDLE hFILE = createfile("First.cpp",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FLIE_ATTRIBUTE_NORMAL,NULL);
以只写方式打开已存在文件
HANDLE hFILE = createfile("First.cpp",GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FLIE_ATTRIBUTE_NORMAL,NULL);
创建一个新文件
HANDLE hFILE = createfile("First.cpp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FLIE_ATTRIBUTE_NORMAL,NULL);
*********************************************************************************************************************
二、向文件中写数据writefile 点击打开链接
bool writefile(
①HANDLE hFile, //文件句柄
②LPCVOID IPBuffer, //数据缓存区指针(LPCVOID 点击打开链接)
③DWORD nNumberofBytesWritten, //你要写的字节数
④LPDWORD IpNumberofBytesWritten, //用于保存实际写入的字节数(LPDWORD 点击打开链接)
⑤LPOVERLAPPED IpOverlapped //OVERLAPPED结构体指针(一般用NULL)
)
用法示例
向打开文件中写入一句话
char buffer[] = {"//hello my first file!!!"};
DWORD writelength;
booi write_ret = wirtefile(hFile,&buffer,strlen(buffer),&writelength,NULL);
三、设置文件指针setfilepointer点击打开链接
在对打开的文件进行操作时需要知道当前文件指针位置,是在文件开头还是文件末尾还是在哪里,打开文件时文件指针默认在文件开头,如果不设置文件指针的话,下次写入文件内容就会覆盖掉前面的内
DWORD WINAPI SetFilePointer(
①HANDLE hFile, //文件句柄
②LONG lDistanceToMove, //32位有符号long型,表示要移动的位置(正数表示向后,负数表示向前)
③PLONG lpDistanceToMoveHigh, //
④DWORD dwMoveMethod //移动模式
);
④dwMoveMethod 移动模式
一共有三种移动模式
FILE_BEGIN 从文件开始位置定位(此时参数②不能为负)
FILE_CURRENT 从文件当前位置向前或向后移动指针(比如写了一句话之后发现写错了,可以将指针移动至写之前的位置,再次写入)
FILE_END 从文件的末尾向前或向后定位指针
返回值:当前所处位置距文件开头的字符数,可以借此查看当前文件有多大
例:将文件指针设置到文件尾部
DWORD pLocation_len = setfilepointer(hFile,0,NULL,FILE_END);
四、判断文件长度GetFileSize(点击打开链接)
DWORD GetFileSize(
HANDLE hFile, //文件句柄
LPDWORD LPFileSizeHigh //指向高阶双字的文件大小的指针(此参数一般为NULL)
);
返回值:返回文件的大小
例:查看已打开文件的长度
DWORD filesize= GetFileSize(hFile,NULL);
五、从文件中读取数据ReadFile(点击打开链接)
BOOL ReadFile(
HANDLE hFile, //文件的句柄
LPVOID lpBuffer, //用于保存读入数据的一个缓冲区
DWORD nNumberOfBytesToRead, //要读入的字符数
LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针
LPOVERLAPPED lpOverlapped //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
);
例:从已打开文件中读取数据
//获取文件大小
int file_length1 = GetFileSize(hFile,NULL);
cout << "文件大小为" << file_length1 << endl;
//从文件中读数据
char * pbuffer11 = (char*)malloc(file_length1 + 1); //创建缓冲区存放读取的内容
DWORD rel_read_len1 = 0;
bool read_ret = ReadFile(hFile,pbuffer11,file_length1,&rel_read_len1,NULL);
{
if(read_ret == 0)
cout << "read file error" << endl;
}
pbuffer11[file_length1] = '\0';
cout << "读到文件全部内容:" << pbuffer11 << endl;
cout << "实际读到的长度" << rel_read_len1 << endl;
free(pbuffer11);
//关闭文件流句柄
CloseHandle(hFile);
六、删除文件DeleteFile
Bool DeleteFile(
LPCSTR lpFileName//要删除的文件名的指针
);
关于删除路径出错问题点击打开链接
例:删除文件
DeleteFile(_T("first.cpp"));
***************************************************************************************************
下面给出具体例子及运行结果
#include
#include
#include
using namespace std;
int main()
{
//创建一个新文件
HANDLE hfile = CreateFile(_T("first.cpp"),GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hfile == INVALID_HANDLE_VALUE)
{
cout << "创建文件失败" << endl;
}
else
{
cout << "first.cpp创建成功" << endl;
}
//// 以只写方式打开已存在的文件
// HANDLE hfile = CreateFile(_T("first.cpp"),GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
//if(INVALID_HANDLE_VALUE == hfile)
//{
// cout << "open file error" << endl;
//}
DWORD plocation_len;
//设置文件指针(打开文件时文件指针默认处于文件开头位置,如果要往里面写数据则需要设置文件指针位置)
plocation_len = SetFilePointer(hfile,0,NULL,FILE_END);
cout << "文件开头距文件指针字节数:" << plocation_len << endl;
//向文件中写入数据
char buffer[] = {"//hello my first create file!!!"}; //创建buffer里面存放要写的内容
DWORD writelength; //创建writelength,里面存放实际写入的长度,可以打印出来
bool write_ret = WriteFile(hfile,&buffer,(DWORD)strlen(buffer),&writelength,NULL);
if(write_ret == 0)
{
cout << " write file fault" << endl;
}
cout << "实际写入长度 " << writelength << endl;
cout << "action over" << endl;
//设置文件指针
plocation_len = SetFilePointer(hfile,0,NULL,FILE_END);
cout << "文件开头距文件指针字节数:" << plocation_len << endl;
//向文件中写入数据
char buffer1[] = {"//ni hao zhong guo!"};
DWORD writelength1; //创建writelength,里面存放实际写入的长度,可以打印出来
bool write_ret1 = WriteFile(hfile,&buffer1,(DWORD)strlen(buffer1),&writelength1,NULL);
if(write_ret1 == 0)
{
cout << " write file fault" << endl;
}
cout << "实际写入长度 " << writelength1 << endl;
cout << "action1 over" << endl;
CloseHandle(hfile);
////设置文件指针(将文件指针设置到文件头)
//plocation_len = SetFilePointer(hfile,0,NULL,FILE_BEGIN);
//cout << "文件开头距文件指针字节数:" << plocation_len << endl;
HANDLE hFile = CreateFile(_T("first.cpp"),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
cout << "open file error" << endl;
}
//获取文件大小
int file_length1 = GetFileSize(hFile,NULL);
cout << "文件大小为" << file_length1 << endl;
//从文件中读数据
char * pbuffer11 = (char*)malloc(file_length1 + 1); //创建缓冲区存放读取的内容
DWORD rel_read_len1 = 0;
bool read_ret = ReadFile(hFile,pbuffer11,file_length1,&rel_read_len1,NULL);
{
if(read_ret == 0)
cout << "read file error" << endl;
}
pbuffer11[file_length1] = '\0';
cout << "读到文件全部内容:" << pbuffer11 << endl;
cout << "实际读到的长度" << rel_read_len1 << endl;
free(pbuffer11);
//关闭文件流句柄
CloseHandle(hFile);
if(DeleteFile(_T("first.cpp")))
{
cout << "first.cpp被删除" << endl;
}
return 0;
}
运行结果
保持更新(后续如用到其他函数会更新本博客)