简体   繁体   English

使用 fread() 和 fwrite 时如何检测读/写错误?

[英]how to detect read/write errors when using fread() and fwrite?

In c i am trying to read/write to a file with fread / fwrite() .在 c 我正在尝试使用fread / fwrite()读取/写入文件。

According to this answer i can use ferror() and feof() to check for errors.根据这个答案,我可以使用ferror()feof()来检查错误。

My question is, how can i use them to do this?我的问题是,我如何使用它们来做到这一点?

The basic recipe is基本配方是

size_t r = fread(buf, m, n, fp);
if(r > 0)
    success;
else if(ferror(fp))
    handle error condition;
else
    handle EOF condition;

Basically, in this case, a 0 return from fread means "either EOF or error", and you have to do something else to figure out which.基本上,在这种情况下,从fread返回 0 表示“EOF 或错误”,您必须执行其他操作才能确定是哪个。 The "something else" is that feof(fp) is true if there was an EOF, and ferror(fp) is true if there was an error. “其他”是如果存在 EOF,则feof(fp)为真,如果存在错误,则ferror(fp)为真。 (Whether it's possible to have both an EOF and error condition at the same time is an interesting question which I am not going to try to answer.) (是否可能同时存在 EOF 和错误条件是一个有趣的问题,我不会尝试回答。)

But, it's true, having both feof() and ferror() available is, mildly, overkill.但是,确实,同时使用feof()ferror()有点矫枉过正。 Typically you only need one or the other.通常,您只需要其中一个。 In the code fragment above I used ferror but not feof .在上面的代码片段中,我使用了ferror但没有使用feof Obviously I could have arranged it a different way:显然我可以用不同的方式安排它:

if(r > 0)
    success;
else if(feof(fp))
    handle EOF condition;
else
    handle error condition;

The other thing to remember, as @chux dicusses in his answer (and I got confused on in a previous version of this answer) is that fread can return less than you asked for.另一件要记住的事情,正如@chux 在他的回答中所讨论的那样(我在这个答案的先前版本中感到困惑)是fread可以返回比你要求的少。 So it's not an error for fread to return a value less than n , but greater than 0 — and this indicates that you've probably hit end-of-file (and feof(fp) would be true).因此, fread返回小于n的值,但大于 0 并不是错误——这表明您可能已经到达文件结尾(并且feof(fp)为真)。

Things are a little different for fwrite , which returns n on success or 0 on total failure. fwrite的情况有些不同,它在成功时返回n ,在完全失败时返回 0。 Theoretically, fwrite can return a number greater than 0 but less than n , and this would indicate, I guess, that it successfully wrote some number of items before it hit an error, but I don't know if that case ever actually happens in practice.从理论上讲, fwrite可以返回一个大于 0 但小于n的数字,我猜这表明它在遇到错误之前成功写入了一些项目,但我不知道这种情况是否真的发生在实践。

@Steve Summit well covers the common cases with code like: @Steve Summit很好地涵盖了以下代码的常见情况:

if (r > 0)
    success;
else if (feof(fp))
    handle EOF condition;
else
    handle error condition;

But we could dig deeper into:但我们可以深入挖掘:

size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);
size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);
  1. fread()/fwrite() returns 0 in 4 cases: fread()/fwrite()在 4 种情况下返回 0:
    1.1. 1.1。 An end-of-file just occurred.刚刚发生了文件结尾。 ( fread() only) (仅限fread()
    1.2. 1.2. An end-of-file had occurred prior.之前发生了文件结束。 ( fread() only) (仅限fread()
    1.3. 1.3. A read/write error just occurred (eg reading a file opened in write only mode or visa-versa, a read parity error, etc.)刚刚发生读/写错误(例如读取以只写模式或反之亦然打开的文件,读取奇偶校验错误等)
    1.4. 1.4. size or nmemb is zero. sizenmemb为零。

  2. Prior to the fread()/fwrite() call, the stream , which has 2 internal flags: end-of-file and error indicators, zero, either one or both of these may be set and are reflected in feof() and ferror() .fread()/fwrite()调用之前, stream有 2 个内部标志:文件结束错误指示符,零,可以设置其中一个或两个,并反映在feof()ferror() Commonly these are both clear before the fread()/fwrite() call, but not always.通常这些在fread()/fwrite()调用之前都是清楚的,但并非总是如此。

  3. Sometimes the amount of data desired to be read/written is less than requested.有时需要读取/写入的数据量少于请求的数据量。

Putting this together for fread()/fwrite()将其放在一起用于fread()/fwrite()

size_t count = fread(ptr, size, nmemb, stream); // or fwrite
if (count == 0) {
  if (feof(stream)) {
    puts("End-of-file.");
  } else if (ferror(stream)) {
    puts("Stream error.");
  } else {
    puts("Request size 0.");  // Case not expected if size, nmemb are both > 0.
  }
} else if (count < nmemb) {
  puts("Less than expected data read/written.");
} else {
  puts("Success.");
}

There is value in checking feof() before ferror() as when the error indicator is set and fread() returns 0 due to end-of-file, the correct failure reason is reported.ferror() feof()是有价值的,因为当设置了错误指示器并且fread()由于文件结束返回 0 时,报告了正确的失败原因。 Note that fread()/fwrite() do not return 0 if the error indicator is set.请注意,如果设置了错误指示符fread()/fwrite()不会返回 0。 They will return 0 if an error is just then detected and then set the error indicator.如果刚刚检测到错误,它们将返回 0,然后设置错误指示器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM