[英]how to detect read/write errors when using fread() and fwrite?
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);
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. size
或nmemb
为零。
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()
调用之前都是清楚的,但并非总是如此。
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.