#include<Windows.h>
#include<iostream>
int main() {
const char* str = "66666好啊好好";
HANDLE hFile = CreateFile("1.txt", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, NULL, NULL);
DWORD count = 0;
if (INVALID_HANDLE_VALUE == hFile) {
fputs("CreateFile failed!", stderr);
exit(1);
}
BOOL ret = WriteFile(hFile, str , strlen(str), &count, NULL);
if (false == ret) {
exit(1);
}
printf("%d\n", count);
//刷新指定缓冲区
FlushFileBuffers(hFile);
CloseHandle(hFile);
HANDLE hFile2 = CreateFile("1.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL);
char buffer[64]{};
DWORD readCount = 0;
BOOL ret2 = ReadFile(hFile2, buffer, 64, &readCount, NULL);
if (false == ret2) {
exit(1);
}
CloseHandle(hFile2);
printf("%s\n", buffer);
}
CreateFileA 函数 (fileapi.h)
反馈
创建或打开文件或 I/O 设备。 最常用的 I/O 设备如下所示:文件、文件流、目录、物理磁盘、卷、控制台缓冲区、磁带驱动器、通信资源、mailslot 和管道。 该函数返回一个句柄,该句柄可用于访问不同类型的 I/O 的文件或设备,具体取决于文件或设备以及指定的标志和属性。
若要将此操作作为事务处理操作执行,这会导致可用于事务处理 I/O 的句柄,请使用 CreateFileTransacted 函数。
语法
C++复制
HANDLE CreateFileA(
[in] LPCSTR lpFileName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwShareMode,
[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
[in] DWORD dwCreationDisposition,
[in] DWORD dwFlagsAndAttributes,
[in, optional] HANDLE hTemplateFile
);
参数
[in] lpFileName
要创建或打开的文件或设备的名称。 可以使用此名称中的正斜杠 (/) 或反斜杠 (\) 。
在此函数的 ANSI 版本中,名称限制为 MAX_PATH 个字符。 若要将此限制扩展到 32,767 宽字符,请调用函数的 Unicode 版本,并将“\\?\”追加到路径。 有关详细信息,请参阅命名文件、路径和命名空间。
有关特殊设备名称的信息,请参阅 定义 MS-DOS 设备名称。
若要创建文件流,请指定文件的名称、冒号,然后指定流的名称。 有关详细信息,请参阅 文件流。
提示从 Windows 10 版本 1607 开始,对于此函数的 unicode 版本 (CreateFileW) ,可以选择加入以删除MAX_PATH限制,而无需追加“\\?\”。。 有关详细信息,请参阅 命名文件、路径和命名空间 的“最大路径长度限制”部分。
[in] dwDesiredAccess
请求访问文件或设备(可以汇总为读取、写入或 0)以指示两者都没有) 。
最常用的值是 GENERIC_READ、 GENERIC_WRITE或两者 () GENERIC_READ | GENERIC_WRITE
。 有关详细信息,请参阅 通用访问权限、 文件安全性和访问权限、 文件访问权限常量和 ACCESS_MASK。
如果此参数为零,则应用程序可以在不访问该文件或设备的情况下查询某些元数据(如文件、目录或设备属性),即使 拒绝了GENERIC_READ 访问。
不能请求与已打开句柄的打开请求中 dwShareMode 参数指定的共享模式冲突的访问模式。
有关详细信息,请参阅本主题的“备注”部分和 “创建和打开文件”。
[in] dwShareMode
文件或设备的请求共享模式,可以读取、写入、删除所有这些或无 (引用下表) 。 对属性或扩展属性的访问请求不受此标志的影响。
如果此参数为零且 CreateFile 成功,则文件或设备无法共享,且在关闭文件或设备的句柄之前无法再次打开。 有关详细信息,请参见“备注”部分。
不能请求与具有打开句柄的现有请求中指定的访问模式冲突的共享模式。 CreateFile 将失败, GetLastError 函数将返回 ERROR_SHARING_VIOLATION。
若要使进程能够在另一个进程打开文件或设备时共享文件或设备,请使用以下一个或多个值的兼容组合。 有关此参数与 dwDesiredAccess 参数的有效组合的详细信息,请参阅 创建和打开文件。
注意 无论进程上下文如何,每个打开句柄的共享选项都将有效,直到关闭该句柄。
[in, optional] lpSecurityAttributes
指向一个 SECURITY_ATTRIBUTES 结构的指针,该结构包含两个独立但相关的数据成员:可选的安全描述符,以及一个布尔值,该值确定返回的句柄是否可以由子进程继承。
此参数可以为 NULL。
如果此参数为 NULL,则应用程序可能创建的任何子进程都无法继承 CreateFile 返回的句柄,并且与返回的句柄关联的文件或设备获取默认的安全描述符。
结构的 lpSecurityDescriptor 成员指定文件或设备的 SECURITY_DESCRIPTOR 。 如果此成员为 NULL,则会为与返回句柄关联的文件或设备分配默认安全描述符。
CreateFile 在打开现有文件或设备时忽略 lpSecurityDescriptor 成员,但继续使用 bInheritHandle 成员。
结构的 bInheritHandle 成员指定是否可以继承返回的句柄。
有关详细信息,请参见“备注”部分。
[in] dwCreationDisposition
对存在或不存在的文件或设备执行的操作。
对于文件以外的设备,此参数通常设置为 OPEN_EXISTING。
有关详细信息,请参见“备注”部分。
此参数必须是下列值之一,不能组合这些值:
[in] dwFlagsAndAttributes
文件或设备属性和标志, FILE_ATTRIBUTE_NORMAL 是文件最常见的默认值。
此参数可以包含可用文件属性的任意组合, (FILE_ATTRIBUTE_*) 。 所有其他文件属性都替代 FILE_ATTRIBUTE_NORMAL。
此参数还可以包含用于控制文件或设备缓存行为、访问模式和其他特殊用途标志的标志 (FILE_FLAG_*) 的组合。 这些值与任何 FILE_ATTRIBUTE_* 值组合在一起。
此参数还可以通过指定 SECURITY_SQOS_PRESENT 标志来包含安全服务质量 (SQOS) 信息。 下表显示了其他与 SQOS 相关的标志信息,这些属性和标志表如下。
注意当 CreateFile 打开现有文件时,它通常将文件标志与现有文件的文件属性组合在一起,并忽略作为 dwFlagsAndAttributes 的一部分提供的任何文件属性。 “创建和打开文件”中详细介绍了特殊情况。
以下某些文件属性和标志只能应用于文件,不一定是 CreateFile 可以打开的所有其他类型的设备。 有关详细信息,请参阅本主题的“备注”部分和 “创建和打开文件”。
有关对文件属性的更高级访问,请参阅 SetFileAttributes。 有关所有文件属性及其值和说明的完整列表,请参阅 文件属性常量。
Attribute | 含义 |
---|---|
FILE_ATTRIBUTE_ARCHIVE 32 (0x20) | 该文件应存档。 应用程序使用此属性来标记要备份或删除的文件。 |
FILE_ATTRIBUTE_ENCRYPTED 16384 (0x4000) | 此文件或目录已加密。 对于文件来说,表示文件中的所有数据都是加密的。 对于目录,这意味着加密是新创建的文件和子目录的默认值。 有关详细信息,请参阅 文件加密。 如果还指定 了FILE_ATTRIBUTE_SYSTEM ,则此标志无效。 家庭版、家庭高级版、初学者版或 ARM 版 Windows 不支持此标志。 |
FILE_ATTRIBUTE_HIDDEN 2 (0x2) | 文件被隐藏。 不要将其包含在普通目录列表中。 |
FILE_ATTRIBUTE_NORMAL 128 (0x80) | 该文件没有设置其他属性。 此属性仅在单独使用时有效。 |
FILE_ATTRIBUTE_OFFLINE 4096 (0x1000) | 文件的数据不能立即可用。 此属性指示文件数据以物理方式移动到脱机存储。 此属性由远程存储(分层存储管理软件)使用。 应用程序不应随意更改此属性。 |
FILE_ATTRIBUTE_READONLY 1 (0x1) | 文件为只读文件。 应用程序可以读取文件,但无法写入或删除该文件。 |
FILE_ATTRIBUTE_SYSTEM 4 (0x4) | 该文件是操作系统的一部分或完全使用的文件。 |
FILE_ATTRIBUTE_TEMPORARY 256 (0x100) | 该文件用于临时存储。 有关详细信息,请参阅本主题的 “缓存行为 ”部分。 |
标志 | 含义 |
---|---|
FILE_FLAG_BACKUP_SEMANTICS 0x02000000 | 正在为备份或还原操作打开或创建该文件。 系统确保调用进程在进程具有 SE_BACKUP_NAME 和 SE_RESTORE_NAME 特权时替代文件安全检查。 有关详细信息,请参阅 更改令牌中的特权。 必须设置此标志才能获取目录的句柄。 目录句柄可以传递给某些函数,而不是文件句柄。 有关详细信息,请参见“备注”部分。 |
FILE_FLAG_DELETE_ON_CLOSE 0x04000000 | 文件在其所有句柄都关闭后立即被删除,其中包括指定的句柄和任何其他打开或重复的句柄。 如果文件存在现有的打开句柄,则调用会失败,除非这些句柄都使用 FILE_SHARE_DELETE 共享模式打开。 针对文件的后续打开请求将失败,除非指定 FILE_SHARE_DELETE 共享模式。 |
FILE_FLAG_NO_BUFFERING 0x20000000 | 文件或设备正在打开,没有系统缓存来读取和写入数据。 此标志不会影响硬盘缓存或内存映射文件。 使用 FILE_FLAG_NO_BUFFERING 标志成功使用 CreateFile 打开的文件有严格的要求,有关详细信息,请参阅文件缓冲。 |
FILE_FLAG_OPEN_NO_RECALL 0x00100000 | 请求文件数据,但它应继续位于远程存储中。 不应将其传输回本地存储。 此标志供远程存储系统使用。 |
FILE_FLAG_OPEN_REPARSE_POINT 0x00200000 | 不会进行正常的 重新分析点 处理; CreateFile 将尝试打开重新分析点。 打开文件时,将返回文件句柄,无论控制重新分析点的筛选器是否正常运行。 此标志不能与 CREATE_ALWAYS 标志一起使用。 如果文件不是重新分析点,则忽略此标志。 有关详细信息,请参见“备注”部分。 |
FILE_FLAG_OVERLAPPED 0x40000000 | 文件或设备正在为异步 I/O 打开或创建。 在此句柄上完成后续 I/O 操作时, 在 OVERLAPPED 结构中指定的事件将设置为信号状态。 如果指定了此标志,则该文件可用于同时读取和写入操作。 如果未指定此标志,则即使对读取和写入函数的调用指定 了 OVERLAPPED 结构,I/O 操作也会序列化。 有关使用此标志创建的文件句柄时的注意事项,请参阅本主题的 同步和异步 I/O 句柄 部分。 |
FILE_FLAG_POSIX_SEMANTICS 0x01000000 | 访问将根据 POSIX 规则进行。 这包括允许具有名称的多个文件,仅在支持该命名的文件系统时有所不同。 使用此选项时应小心,因为使用此标志创建的文件可能无法由为 MS-DOS 或 16 位 Windows 编写的应用程序访问。 |
FILE_FLAG_RANDOM_ACCESS 0x10000000 | 访问是随机的。 系统可将此选项用作优化文件缓存的提示。 如果文件系统不支持缓存的 I/O 和 FILE_FLAG_NO_BUFFERING,则此标志无效。 有关详细信息,请参阅本主题的 “缓存行为 ”部分。 |
FILE_FLAG_SESSION_AWARE 0x00800000 | 文件或设备正在使用会话感知打开。 如果未指定此标志,则会话中的每个会话设备 ((例如使用 RemoteFX USB 重定向的设备) )无法由会话 0 中运行的进程打开。 对于不在会话 0 中的调用方,此标志无效。 此标志仅在 Windows 的服务器版本上受支持。 Windows Server 2008 R2 和 Windows Server 2008: Windows Server 2012之前不支持此标志。 |
FILE_FLAG_SEQUENTIAL_SCAN 0x08000000 | 访问旨在从头到尾的顺序。 系统可将此选项用作优化文件缓存的提示。 如果读取隐藏 ((即使用反向扫描) ),则不应使用此标志。 如果文件系统不支持缓存的 I/O 和 FILE_FLAG_NO_BUFFERING,则此标志无效。 有关详细信息,请参阅本主题的 “缓存行为 ”部分。 |
FILE_FLAG_WRITE_THROUGH 0x80000000 | 写入操作不会经历任何中间缓存,它们将直接转到磁盘。 有关详细信息,请参阅本主题的 “缓存行为 ”部分。 |
dwFlagsAndAttributes 参数还可以指定 SQOS 信息。 有关详细信息,请参阅 模拟级别。 当调用应用程序将 SECURITY_SQOS_PRESENT 标志指定为 dwFlagsAndAttributes 的一部分时,它还可以包含以下一个或多个值。
[in, optional] hTemplateFile
具有 GENERIC_READ 访问权限的模板文件的有效句柄。 模板文件为正在创建的文件提供文件属性和扩展属性。
此参数可以为 NULL。
打开现有文件时, CreateFile 将忽略此参数。
打开新的加密文件时,该文件将从其父目录继承任意访问控制列表。 有关详细信息,请参阅 文件加密。
返回值
如果函数成功,则返回值是指定文件、设备、命名管道或邮件槽的打开句柄。
如果函数失败,则返回值为 INVALID_HANDLE_VALUE。 要获得更多的错误信息,请调用 GetLastError。
注解
CreateFile 最初专为文件交互而开发,但此后已扩展和增强,以包括 Windows 开发人员可用的大多数其他类型的 I/O 设备和机制。 本部分尝试介绍开发人员在不同上下文中使用不同的 I/O 类型使用 CreateFile 时可能遇到的各种问题。 仅当专门引用存储在文件系统上实际文件中的数据时,文本才会尝试使用单词 文件 。 但是,某些文件用法可能更普遍地引用支持类似 文件的 I/O 对象。 由于前面提到的历史原因,这种自由使用术语 文件 在常量名称和参数名称中尤其普遍。
使用 CreateFile 返回的对象句柄完成应用程序后,请使用 CloseHandle 函数关闭句柄。 这不仅释放了系统资源,而且可以对共享文件或设备以及将数据提交到磁盘等内容产生更广泛的影响。 本主题中会相应地说明具体内容。
Windows Server 2003 和 Windows XP: 如果尝试打开文件或目录以在远程计算机上删除,则发生共享冲突,当 dwDesiredAccess 参数的值是使用任何其他访问标志 (0x00010000) OR'ed 的 DELETE 访问标志,并且远程文件或目录尚未使用FILE_SHARE_DELETE打开。 为了避免此方案中的共享冲突,请仅打开具有 DELETE 访问权限的远程文件或目录,或者调用 DeleteFile ,而无需首先打开文件或目录进行删除。
某些文件系统(如 NTFS 文件系统)支持单个文件和目录的压缩或加密。 对于具有此支持的装载文件系统的卷,新文件继承其目录的压缩和加密属性。
不能使用 CreateFile 来控制文件或目录上的压缩、解压缩或解密。 有关详细信息,请参阅 创建和打开文件、 文件压缩和解压缩以及 文件加密。
Windows Server 2003 和 Windows XP: 出于向后兼容性目的,在 lpSecurityAttributes 中指定安全描述符时,CreateFile 不会应用继承规则。 为了支持继承,以后查询此文件的安全描述符的函数可能会启发性地确定并报告继承是否有效。 有关详细信息,请参阅 可继承 ACE 的自动传播。
如前所述,如果 lpSecurityAttributes 参数为 NULL,则应用程序可能创建的任何子进程都无法继承 CreateFile 返回的句柄。 有关此参数的以下信息也适用:
- 如果 bInheritHandle 成员变量不是 FALSE,这是任何非零值,则可以继承句柄。 因此,如果不希望句柄可继承,则此结构成员必须正确初始化为 FALSE 。
- 访问控制列表 (文件或目录的默认安全描述符中的 ACL) 继承自其父目录。
- 目标文件系统必须支持 lpSecurityDescriptor 成员对文件和目录的安全性,才能对其产生影响,这可以通过 使用 GetVolumeInformation 来确定。
WriteFile 函数 (fileapi.h)
反馈
将数据写入指定的文件或输入/输出 (I/O) 设备。
此函数适用于同步和异步操作。 有关专为异步操作设计的类似函数,请参阅 WriteFileEx。
语法
C++复制
BOOL WriteFile(
[in] HANDLE hFile,
[in] LPCVOID lpBuffer,
[in] DWORD nNumberOfBytesToWrite,
[out, optional] LPDWORD lpNumberOfBytesWritten,
[in, out, optional] LPOVERLAPPED lpOverlapped
);
参数
[in] hFile
文件或 I/O 设备的句柄 (例如文件、文件流、物理磁盘、卷、控制台缓冲区、磁带驱动器、套接字、通信资源、mailslot 或管道) 。
必须使用写入访问权限创建 hFile 参数。 有关详细信息,请参阅 通用访问权限 和 文件安全性和访问权限。
对于异步写入操作,hFile 可以是使用FILE_FLAG_OVERLAPPED标志或套接字句柄或接受函数返回的 CreateFile 函数打开的任何句柄。
[in] lpBuffer
指向包含要写入文件或设备的数据的缓冲区的指针。
此缓冲区必须在写入操作期间保持有效。 在写入操作完成之前,调用方不得使用此缓冲区。
[in] nNumberOfBytesToWrite
要写入文件或设备的字节数。
值为零指定 null 写入操作。 null 写入操作的行为取决于基础文件系统或通信技术。
Windows Server 2003 和 Windows XP: 跨网络管道写入操作的大小限制为每个写入。 每个平台的金额各不相同。 对于 x86 平台,它为 63.97 MB。 对于 x64 平台,它为 31.97 MB。 对于 Itanium,它为 63.95 MB。 有关管道的详细信息,请参阅“备注”部分。
[out, optional] lpNumberOfBytesWritten
指向使用同步 hFile 参数时写入的字节数的变量的指针。 WriteFile 将此值设置为零,然后再执行任何工作或错误检查。 如果这是一个异步操作,请对此参数使用 NULL ,以避免潜在的错误结果。
仅当 lpOverlapped 参数不为 NULL 时,此参数才可为 NULL。
Windows 7: 此参数不能为 NULL。
有关详细信息,请参见“备注”部分。
[in, out, optional] lpOverlapped
如果使用 FILE_FLAG_OVERLAPPED打开 hFile 参数,则需要指向 OVERLAPPED 结构的指针,否则此参数可以为 NULL。
对于支持字节偏移量的 hFile ,如果使用此参数,则必须指定开始写入文件或设备的字节偏移量。 通过设置 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员来指定此偏移量。 对于不支持字节偏移量的 hFile,将忽略 Offset 和 OffsetHigh。
若要写入文件末尾,请将 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员指定为0xFFFFFFFF。 这在功能上等效于以前调用 CreateFile 函数以使用FILE_APPEND_DATA访问打开 hFile。
有关 lpOverlapped 和 FILE_FLAG_OVERLAPPED的不同组合的详细信息,请参阅“备注”部分和 “同步和文件位置 ”部分。
返回值
如果函数成功,则返回值为非零 (TRUE) 。
如果函数失败或异步完成,则返回值为零, (FALSE) 。 若要获取扩展的错误信息,请调用 GetLastError 函数。
注意GetLastError 代码ERROR_IO_PENDING不是失败;它指定写入操作正在异步完成。 有关详细信息,请参阅“备注”。
注解
当出现以下情况之一时, WriteFile 函数将返回:
- 所请求的字节数是写入的。
- 读取操作在管道的读取端释放缓冲区空间, (如果写入被阻止) 。 有关详细信息,请参阅 “管道” 部分。
- 正在使用异步句柄,写入正在异步发生。
- 发生错误。
每当有过多未完成的异步 I/O 请求时,WriteFile 函数可能会失败,ERROR_INVALID_USER_BUFFER或ERROR_NOT_ENOUGH_MEMORY。
若要取消所有挂起的异步 I/O 操作,请使用以下任一操作:
- CancelIo - 此函数仅取消由指定文件句柄的调用线程发出的操作。
- CancelIoEx - 此函数取消指定文件句柄的线程发出的所有操作。
使用 CancelSynchronousIo 函数取消挂起的同步 I/O 操作。
取消的 I/O 操作已完成,错误 ERROR_OPERATION_ABORTED。
WriteFile 函数可能会失败,ERROR_NOT_ENOUGH_QUOTA,这意味着调用进程的缓冲区无法锁定页。 有关详细信息,请参阅 SetProcessWorkingSetSize。
如果文件的一部分被另一个进程锁定,并且写入操作与锁定部分重叠, 则 WriteFile 将失败。
写入文件时,直到所有用于写入的句柄都已关闭,最后一次写入时间不会完全更新。 因此,若要确保上次写入时间准确,请在写入文件后立即关闭文件句柄。
在写入操作使用缓冲区时访问输出缓冲区可能会导致从该缓冲区写入的数据损坏。 应用程序不得写入、重新分配或释放写入操作正在使用的输出缓冲区,直到写入操作完成。 使用异步文件句柄时,这尤其有问题。 有关同步与异步文件句柄的其他信息,请参阅“ 同步和文件位置 ”部分以及 同步和异步 I/O。
请注意,远程文件可能无法正确更新时间戳。 若要确保结果一致,请使用无缓冲区 I/O。
系统将零字节解释为指定 null 写入操作, WriteFile 不会截断或扩展文件。 若要截断或扩展文件,请使用 SetEndOfFile 函数。
可以使用 WriteFile 和控制台输出句柄将字符写入屏幕缓冲区。 函数的确切行为由控制台模式确定。 数据将写入当前游标位置。 写入操作后将更新游标位置。 有关控制台句柄的详细信息,请参阅 CreateFile。
写入通信设备时, WriteFile 的行为由当前通信超时确定为集,并使用 SetCommTimeouts 和 GetCommTimeouts 函数进行检索。 如果无法设置超时值,则可能会出现不可预知的结果。 有关通信超时的详细信息,请参阅 COMMTIMEOUTS。
尽管单扇区写入是原子的,但多扇区写入不能保证是原子的,除非使用事务 (,否则创建的句柄是事务处理句柄;例如,使用 CreateFileTransacted) 创建的句柄。 缓存的多扇区写入可能不会始终立即写入磁盘;因此,在 CreateFile 中指定FILE_FLAG_WRITE_THROUGH,以确保将整个多扇区写入磁盘,而不会造成潜在的缓存延迟。
如果直接写入已装载文件系统的卷,必须先获取对卷的独占访问权限。 否则,可能会造成数据损坏或系统不稳定,因为应用程序的写入可能会与其他来自文件系统的更改冲突,并使卷的内容处于不一致状态。 为了防止这些问题,Windows Vista 及更高版本中进行了以下更改:
- 如果卷没有装载文件系统,或者下列条件之一为 true,则卷句柄上的写入将成功:
- 要写入到的扇区是启动扇区。
- 要写入到的扇区驻留在文件系统空间之外。
- 已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME显式锁定或卸载卷。
- 卷没有实际的文件系统。 (换句话说,它装载了 RAW 文件系统。)
- 如果以下条件之一为 true,则磁盘句柄上的写入将成功:
- 要写入的扇区不属于卷的盘区。
- 要写入到位于装载卷内的扇区,但已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME显式锁定或卸载卷。
- 要写入到的扇区属于没有原始装载文件系统的卷。
使用 FILE_FLAG_NO_BUFFERING 成功使用 CreateFile 打开的文件有严格的要求。 有关详细信息,请参阅 文件缓冲。