在 C 中检查 fwrite 是不是成功,perror

Posted

技术标签:

【中文标题】在 C 中检查 fwrite 是不是成功,perror【英文标题】:Checking for success of fwrite in C, perror在 C 中检查 fwrite 是否成功,perror 【发布时间】:2011-01-20 18:03:22 【问题描述】:

使用 fwrite 返回成功写入文件的元素数,方法是:

if (!(fwrite(...))) 
    fprintf(stderr, "Failure");
    //perror(???)  I sometimes see code that says perror here and I don't know 
    //exactly what this does.

这是否检查是否成功写入文件?还有其他需要担心的事情吗?

谢谢。

【问题讨论】:

【参考方案1】:

简而言之,不完全是。 fwrite 返回成功写入的元素个数;您需要根据您打算编写的元素数量检查这一点,即您将参数传递给 fwrite 的那些。

您所做的检查是否已写入某些元素。

这是perror 的参考。

解释全局的值 将变量 errno 转换为字符串和 将该字符串打印到标准错误(标准 错误输出流,通常是 屏幕),可选地在它前面加上 str 中指定的自定义消息。 errno 是一个整数变量,其 值描述了最后一个错误 通过调用库产生 功能。产生的错误字符串 错误取决于发展 平台和编译器。如果 参数 str 不是空指针, 打印 str 后跟一个冒号 (:) 和一个空间。那么,str 是否为 空指针与否,生成 随后打印错误描述 通过换行符 ('\n')。错误 应该在错误发生后立即调用 已生产,否则可以 在对其他人的调用中被覆盖 功能。

【讨论】:

如果您安排始终使用大小为len1 元素来调用fwrite,则无需将其与元素数量进行比较。那么可能的返回值只有 0 和 1,0 表示任何失败,1 表示成功。【参考方案2】:

您的代码可能无法正确检查错误。使用

if (fwrite(ptr, size, num, f) != num) 
    // An error occurred, handle it somehow

【讨论】:

@mctylr:错了。 fwrite 根本无法处理 EAGAINEINTR。他们将为流设置错误指示器,并且没有办法在不丢失或重复数据的情况下恢复写入(由于不知道缓冲区的状态)。如果你想使用中断信号或者想将文件设置为非阻塞,stdio 一般是不可用的。【参考方案3】:

来自 fwrite 的 Linux 手册页

fread() 和 fwrite() 返回成功读取的项目数或 书面(即,不是字符数)。如果发生错误,或 到达文件结尾,返回值是一个短项目计数(或 零)。

因此您需要与预期的返回值进行比较。

在许多情况下,您可能需要检查errno 是否等于EAGAINEINTR,在这种情况下,您通常希望重试写入请求,而在其他情况下,您希望处理短写入优雅地。

对于 fwrite,在 short write 上(写入的数据少于您的全部数据)您可以检查 feof() 和/或 ferror() 以查看流是否正在返回和结束-file,EOF,例如 PIPE 是否关闭,或者流是否设置了错误诱导标志。

【讨论】:

查看我对您其他评论的评论。像你说的那样重试会导致重复失败和/或数据损坏。 是的,我确实搞砸了,而且我已经消除了我最初的错误。据我了解,一个程序可能会在安全地调用clearerr() 之后尝试调用fwrite(),再次检查是否有持续的错误/失败/EOF。【参考方案4】:
STRERROR(3)            FreeBSD Library Functions Manual            STRERROR(3)

NAME
     perror, strerror, strerror_r, sys_errlist, sys_nerr — system error mes‐
     sages

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdio.h>

     void
     perror(const char *string);

     ...

DESCRIPTION
     ...

     The perror() function finds the error message corresponding to the cur‐
     rent value of the global variable errno (intro(2)) and writes it, fol‐
     lowed by a newline, to the standard error file descriptor.  If the argu‐
     ment string is non‐NULL and does not point to the null character, this
     string is prepended to the message string and separated from it by a
     colon and space (“: ”); otherwise, only the error message string is
     printed.

...

STANDARDS
     The perror() and strerror() functions conform to ISO/IEC 9899:1999
     (“ISO C99”).  ...

【讨论】:

【参考方案5】:

您还可以使用explain_fwrite()explain_errno_fwrite、...来自libexplain

man page 解释:

explain_fwrite 函数用于获取对fwrite(3) 系统调用返回的错误的解释。消息中最少包含strerror(errno) 的值,但通常会做得更好,并更详细地指出根本原因。

errno 全局变量将用于获取要解码的错误值。

此函数旨在以类似于以下示例的方式使用(此处的手册页错误,正如下面的评论中 @puchu 正确指出的那样。我更正了代码以解决该问题):

if (fwrite(ptr, size, nmemb, fp) < nmemb)

    fprintf(stderr, "%s\n", explain_fwrite(ptr, size, nmemb, fp));
    exit(EXIT_FAILURE);

警告:此方法不是线程安全的。

【讨论】:

fwrite 返回size_tsize_t 是无符号值。无法&lt; 0 @puchu:谢谢。你说的对。手册页是错误的。请查看正确答案。

以上是关于在 C 中检查 fwrite 是不是成功,perror的主要内容,如果未能解决你的问题,请参考以下文章

linux下php fwrite无法写入文件怎么回事呀

c语言fwrite写文件失败

56.fread fwrite

fread 和 fwrite 有没有失败?如何处理?

c语言中fread的用法

如何在目标c中检查用户是不是登录?