setFilePointer 函数 (fileapi.h)
移动指定文件的文件指针。
此函数将文件指针存储在两 个 LONG 值中。 若要使用大于单个 LONG 值的文件指针,可以更轻松地使用 SetFilePointerEx 函数。
语法
DWORD SetFilePointer(
[in] HANDLE hFile,
[in] LONG lDistanceToMove,
[in, out, optional] PLONG lpDistanceToMoveHigh,
[in] DWORD dwMoveMethod
);
参数
[in] hFile
文件的句柄。
必须使用 GENERIC_READ 或 GENERIC_WRITE 访问权限创建文件句柄。 有关详细信息,请参阅 文件安全性和访问权限。
[in] lDistanceToMove
有符号值的低序 32 位,指定移动文件指针的字节数。
如果 lpDistanceToMoveHigh 不为 NULL, 则 lpDistanceToMoveHigh 和 lDistanceToMove 将形成一个 64 位有符号值,该值指定移动距离。
如果 lpDistanceToMoveHigh 为 NULL, 则 lDistanceToMove 为 32 位有符号值。 lDistanceToMove 的正值将文件指针向前移动,负值将文件指针移回。
[in, out, optional] lpDistanceToMoveHigh
指向要移动的有符号 64 位距离的高阶 32 位的指针。
如果不需要高阶 32 位,则必须将此指针设置为 NULL。
如果不是 NULL,则此参数还接收文件指针的新值的高阶 DWORD 。 有关详细信息,请参阅本主题中的“备注”部分。
[in] dwMoveMethod
文件指针移动的起点。
此参数的取值可为下列值之一:
值 | 含义 |
---|---|
|
起始点为零或文件的开头。 |
|
起点是文件指针的当前值。 |
|
起点是当前文件结束位置。 |
返回值
如果函数成功且 lpDistanceToMoveHigh 为 NULL,则返回值为新文件指针的低序 DWORD 。 注意 如果函数返回 除 INVALID_SET_FILE_POINTER 以外的值,则对 SetFilePointer 的调用已成功。 无需调用 GetLastError。
如果函数成功且 lpDistanceToMoveHigh 不为 NULL,则返回值为新文件指针的低序 DWORD,lpDistanceToMoveHigh 包含新文件指针的高阶 DWORD。
如果函数失败,则返回值 INVALID_SET_FILE_POINTER。 要获得更多的错误信息,请调用 GetLastError。
如果新的文件指针为负值,则函数失败,不会移动文件指针,并且 GetLastError 返回的代码 ERROR_NEGATIVE_SEEK。
如果 lpDistanceToMoveHigh 为 NULL ,并且新文件位置不适合 32 位值,则该函数将失败并返回 INVALID_SET_FILE_POINTER。
注解
由 hFile 参数的值标识的文件指针不用于重叠的读取和写入操作。
hFile 参数必须引用存储在查找设备上的文件;例如,磁盘卷。 即使 SetFilePointer 函数可能不会返回错误,也不支持使用句柄调用非查找设备(如管道或通信设备) 的 SetFilePointer 函数。 在这种情况下, SetFilePointer 函数的行为未定义。
指定重叠操作的偏移量
- 使用 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员。
确定 hFile 的文件类型
- 使用 GetFileType 函数。
在多线程应用程序中设置文件指针时请小心。 必须同步对共享资源的访问。 例如,具有共享文件句柄、更新文件指针和从文件读取的线程的应用程序必须使用关键节对象或互斥对象来保护此序列。 有关详细信息,请参阅 Critical Section 对象 和 互斥对象。
如果 hFile 句柄打开时设置了 FILE_FLAG_NO_BUFFERING 标志,则应用程序只能将文件指针移动到扇区对齐的位置。 扇区对齐位置是卷扇区大小的整数倍数的仓位。 应用程序可以通过调用 GetDiskFreeSpace 函数来获取卷扇区大小。
如果应用程序调用具有距离的 SetFilePointer 来移动导致位置不与扇区对齐的值以及使用 FILE_FLAG_NO_BUFFERING 打开的句柄,则函数将失败, GetLastError 将返回 ERROR_INVALID_PARAMETER。
将文件指针设置为文件末尾以外的位置不是错误。 在调用 SetEndOfFile、WriteFile 或 WriteFileEx 函数之前,文件大小不会增加。 写入操作会将文件的大小增加到文件指针位置,以及写入的缓冲区的大小,这会导致干预字节被初始化为零。
如果返回值为 INVALID_SET_FILE_POINTER 并且 lpDistanceToMoveHigh 为非 NULL,则应用程序必须调用 GetLastError 来确定函数是成功还是失败。 下面的代码示例演示了该方案。
// Case One: calling the function with lpDistanceToMoveHigh == NULL
// Try to move hFile file pointer some distance
DWORD dwPtr = SetFilePointer( hFile,
lDistance,
NULL,
FILE_BEGIN );
if (dwPtr == INVALID_SET_FILE_POINTER) // Test for failure
{
// Obtain the error code.
DWORD dwError = GetLastError() ;
// Deal with failure
// . . .
} // End of error handler
//
// Case Two: calling the function with lpDistanceToMoveHigh != NULL
// Try to move hFile file pointer a huge distance
DWORD dwPtrLow = SetFilePointer( hFile,
lDistLow,
&lDistHigh,
FILE_BEGIN );
// Test for failure
if ( dwPtrLow == INVALID_SET_FILE_POINTER &&
GetLastError() != NO_ERROR )
{
// Deal with failure
// . . .
} // End of error handler
尽管参数 lpDistanceToMoveHigh 用于操作大型文件,但在移动任何大小的文件时,应设置参数的值。 如果设置为 NULL,则 lDistanceToMove 的最大值为 2^31–2,或 2 GB,因为所有文件指针值都是有符号值。 因此,如果文件增加到该大小的可能性很小,最好将文件视为大型文件并使用 64 位文件指针。 使用 NTFS 文件系统上的 文件压缩 和 稀疏文件,即使基础卷不是很大,也有可能具有较大的文件。
如果 lpDistanceToMoveHigh 不为 NULL,则 lpDistanceToMoveHigh 和 lDistanceToMove 将形成单个 64 位有符号值。 lDistanceToMove 参数被视为值的低序 32 位,将 lpDistanceToMoveHigh 视为高阶 32 位,这意味着 lpDistanceToMoveHigh 是 lDistanceToMove 的符号扩展。
若要将文件指针从 0 GB 移动到 2 GB,必须将 lpDistanceToMoveHigh 设置为 NULL 或 lDistanceToMove 的符号扩展。 若要移动指针超过 2 GB,请使用 lpDistanceToMoveHigh 和 lDistanceToMove 作为单个 64 位数量。 例如,若要在 2 GB 到 4 千兆字节的范围内移动,请将 lpDistanceToMoveHigh 的内容设置为零,或设置为 –1(对于 lDistanceToMove 的负号扩展)。
若要使用 64 位文件指针,可以声明 LONG,将其视为 64 位文件指针的上半部分,并在 lpDistanceToMoveHigh 中传递其地址。 这意味着,你必须将两个不同的变量视为一个逻辑单元,这可能会导致错误。 最好使用 LARGE_INTEGER 结构创建 64 位值,并使用联合的相应元素传递两个 32 位值。
此外,最好使用 函数来隐藏 SetFilePointer 的接口。 下面的代码示例演示了该方案。
__int64 myFileSeek (HANDLE hf, __int64 distance, DWORD MoveMethod)
{
LARGE_INTEGER li;
li.QuadPart = distance;
li.LowPart = SetFilePointer (hf,
li.LowPart,
&li.HighPart,
MoveMethod);
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError()
!= NO_ERROR)
{
li.QuadPart = -1;
}
return li.QuadPart;
}
可以使用 SetFilePointer 来确定文件的长度。 为此,请将 FILE_END 用于 dwMoveMethod 并查找位置零。 返回的文件偏移量是文件的长度。 但是,这种做法可能会产生意外的副作用,例如,无法保存当前文件指针,以便程序可以返回到该位置。 最好改用 GetFileSize 。
还可以使用 SetFilePointer 函数来查询当前文件指针位置。 为此,请指定 移动方法FILE_CURRENT ,距离为零。
在 Windows 8 和 Windows Server 2012 中,此函数由以下技术支持。
技术 | 支持 |
---|---|
服务器消息块 (SMB) 3.0 协议 | 是 |
SMB 3.0 透明故障转移 (TFO) | 是 |
具有横向扩展文件共享的 SMB 3.0 (SO) | 是 |
群集共享卷文件系统 (CSV) | 是 |
弹性文件系统 (ReFS) | 是 |
示例
有关追加文件的代码示例,请参阅 将一个文件追加到另一个文件。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows XP [桌面应用 | UWP 应用] |
最低受支持的服务器 | Windows Server 2003 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | fileapi.h (包括 Windows.h) |
Library | Kernel32.lib |
DLL | Kernel32.dll |