一篇文章建议:“在调用
SetFilePointer
之前必须先调用 SetEndOfFile
”,但是 SetFilePointer
的文档明确指出:“由 hFile 参数的值标识的文件指针不用于重叠读写操作。”。
编辑:我用
FILE_FLAG_OVERLAPPED
打开了一个文件,对 4MB 进行了 SetFilePointer
操作,并调用了 SetEndOfFile
。然后,我将 SetFilePointer
从 FILE_BEGIN
中删除为零字节,然后将 OVERLAPPED
结构的 Offset
和 OffsetHigh
标志设置为 0xFFFFFFFF
写入它。写入发生在文件末尾,即从 4MB 标记开始。
“由hFile的值标识的文件指针 参数不用于重叠的 read 和 write 操作。”
是的。这是对的。但不适用于所有 I/O 操作,而仅适用于读和写(以及其他几个),但不适用于 SetFilePointer(
NtSetInformationFile
和 FilePositionInformation
)
FILE_OBJECT
结构 - CurrentByteOffset - 指定与文件对象关联的文件偏移量(以字节为单位)的成员 - 以及 win32 中所谓的 文件指针
注意,该成员基本上由 I/O 管理器本身管理,而不是由(文件系统)驱动程序管理。我们可以通过调用 和
NtSetInformationFile
和 FilePositionInformation
来获取和设置该成员
尽管这里指出:
这并不完全正确,即使文件在没有此标志的情况下打开(即使用调用者必须使用 CreateOptions 中指定的 FILE_SYNCHRONOUS_IO_ALERT 或 FILE_SYNCHRONOUS_IO_NONALERT 标志打开文件 参数。
FILE_FLAG_OVERLAPPED
) - 通常可以这样做(取决于 drom 驱动程序实现)。简单地说,如果文件作为同步打开 - 此操作由 I/O 管理器本身处理(甚至不调用驱动程序)。如果是异步文件 - 请求传递给驱动程序。文件系统驱动程序(fastfat、ntfs)也通过更新来处理此请求
CurrentByteOffset
。为什么要这样读/写?因为要查找此 api 的签名 - 它具有(同步句柄可选)
ByteOffset
参数 - 如果存在 - 它会使用,否则它取自
CurrentByteOffset
中的
FILE_OBJECT
。对于异步句柄 -
ByteOffset
是强制参数 - 它始终不能为 0(或系统返回错误无效参数) - 因此
CurrentByteOffset
在异步读/写 I/O 中从未使用过。但这与
NtSetInformationFile
无关
SetFilePointer
是什么?它用
NtSetInformationFile
调用
FilePositionInformation
(实际上它也调用 和
NtQueryInformationFile
)。
SetEndOfFile
是什么?它首先使用
NtQueryInformationFile
调用
FilePositionInformation
- 获取
CurrentByteOffset
的值(由
SetFilePointer
设置),然后使用
NtSetInformationFile
和
FileEndOfFileInformation
调用
FileAllocationInformation
(此调用仅是优化)。所以
SetFilePointer
与
SetEndOfFile
适用于任何文件。但效率不高。我建议根本不要使用
SetFilePointer
。对于具体任务 - 只需调用
NtSetInformationFile
(最好的),或者如果您不喜欢 ntapi - 使用
SetFileInformationByHandle
与 FileEndOfFileInfo
+
FileAllocationInfo
FILE_END_OF_FILE_INFO eof = { * };
SetFileInformationByHandle(hFile, FileEndOfFileInfo, &eof, sizeof(eof));
SetFileInformationByHandle(hFile, FileAllocationInfo, &eof, sizeof(eof));