【问题标题】:To check SetFilePointerEx, ReadFile or WriteFile for success do I need to check lpNewFilePointer, lpNumberOfBytesRead and lpNumberOfBytesWritten?要检查 SetFilePointerEx、ReadFile 或 WriteFile 是否成功,我需要检查 lpNewFilePointer、lpNumberOfBytesRead 和 lpNumberOfBytesWritten 吗?
【发布时间】:2017-07-22 00:42:04
【问题描述】:

我对 SetFilePointerEx、ReadFile 和 WriteFile API 感到有些困惑。比如说,如果我想将文件指针移动到一个新位置,这样做是否足够:

if(SetFilePointerEx(hFile, liPtr, NULL, FILE_BEGIN))
{
    //Success, moved file pointer to liPtr position
}

或者,我是否也需要检查lpNewFilePointer 中返回的值?

LARGE_INTEGER liSetTo = {0};
if(SetFilePointerEx(hFile, liPtr, &liSetTo, FILE_BEGIN) &&
    liPtr.QuadPart == liSetTo.QuadPart)
{
    //Success
}

这同样适用于 ReadFile 和 WriteFile。例如:

if(WriteFile(hFile, buffer, numberBytesToWrite, NULL, NULL))
{
    //Success writing numberBytesToWrite into file
}

或者我需要这样做以确保我的所有数据都写入成功:

DWORD numberBytesWritten = 0;
if(WriteFile(hFile, buffer, numberBytesToWrite, &numberBytesWritten, NULL) &&
    numberBytesWritten == numberBytesToWrite)
{
    //Success writing numberBytesToWrite into file
}

换句话说,拥有这些返回大小和偏移量有什么意义?我的意思是,如果我想让它把 1024 个字节写入一个文件,它可以只写 1000 个字节。 :) 如果它没有写入我请求它的所有数据,那会不会构成错误,或者从 API 返回FALSE

无论如何,如果有人能澄清一下,我将不胜感激。

【问题讨论】:

  • setpointer 从文件开头返回新位置。至于读/写,是的,它们可以返回成功,但读/写你指定的字节数更少。
  • @geza:在我的示例中,WriteFile 在什么情况下会返回TRUEnumberBytesToWrite != numberBytesWritten
  • 一个实例,当磁盘已满(或达到用户的存储配额)时,WriteFile 不会写入请求的数量。到达文件末尾时,ReadFile 将读取更少。
  • 一个例子是来自命名管道的 ReadFile 将在相应的写操作结束时返回。因此,如果您要求 10 个字节,但管道另一端的进程只发送 5 个,那么您只会得到 5 个。此外,非阻塞套接字可能读取和/或写入的字节数少于请求的字节数。我不认为写入普通文件会写入比请求更少的字节数。
  • @RbMm:Zw*/Nt* 函数不是 Windows API 的一部分。没有关于可用性的明确合同公布。它们可以在未来的版本中被删除(不太可能),应用额外的限制(例如,只能从签名的二进制文件中调用),或者被安全软件阻止,除非从受信任的系统模块调用。

标签: c++ winapi


【解决方案1】:

对于SetFilePointerEx,您应该只检查它的返回值。它包含操作是否成功。

对于同步的ReadFile/WriteFile,如果返回false,则操作完全失败(根本没有读取/写入字节)。如果它返回真,那么你应该检查lpNumberOfBytesRead/lpNumberOfBytesWritten,因为它可以低于你指定的数字。例如,对于读取,如果达到 EOF,那么您将得到一个简短的读取。对于写入,如果在写入过程中磁盘已满,您可能会得到一个短写入。

短读/写可能还有其他各种原因,因此您的代码应该处理这些情况。

【讨论】:

  • 对于ReadFile/WriteFile,如果返回false,则操作完全失败 ... 仔细阅读文档:如果函数失败,或者是异步完成,返回值为零(FALSE)。
  • @zett42:添加了“同步”
  • @zett42 - 问题的表述方式隐含假设同步操作。如果异步 io (当返回挂起时) NumberOfBytesRead 未定义(尚未填充)。并且对于同步 io 答案是正确的
  • 如果磁盘已满,写入将失败 - 它不会进行部分写入。 (无论如何,不​​在 NTFS 上 - 我刚刚检查过。)
  • (这只是一个挑剔,请注意,我同意您应该始终检查是否读取或写入了预期的字节数。+1。我通常会将短写入视为错误条件。 )
猜你喜欢
  • 2021-11-06
  • 1970-01-01
  • 2020-08-14
  • 2011-02-21
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 2016-11-02
相关资源
最近更新 更多