【问题标题】:C fopen mode read+write+createC fopen模式读+写+创建
【发布时间】:2026-01-09 01:00:01
【问题描述】:

我想要:

  1. 如果文件不存在则创建,not overwritten if it does
  2. 在任何我想要的地方读写和fseek

我找不到有效的模式——“w+”、“rw”、“rwb+”、“r+b”、“w+b”、“a+”还是什么?

表现良好的基础级别'open'是:

int fd =open("fname", O_RDWR | O_CREAT, 0666);

但我想知道fopen alternative。 我尝试的每个模式字母 [w, r, a, +] 组合要么覆盖内容,要么 fseek-fwrite 不写在它应该写的地方。无论fseek 设置什么,“a+”都将始终追加...“rw+”可以正常工作,但不会创建不存在的文件...等。

更新:澄清为什么例如“a+”不是解决方案:

#include <stdio.h>
int main()
{  FILE *fp =fopen("aaa.txt", "a+");
   fwrite("aaaaaaaaaaaaaaaaaaa", 1, 10, fp);
   fseek(fp, 5, SEEK_SET);
   fwrite("AAA", 1, 3, fp);
   fclose(fp);
   return 0;
}
runned with: $ rm aaa.txt; gcc test.c && ./a.out && cat aaa.txt && echo .
produces wrong result:  aaaaaaaaaaAAA.
     result should be:  aaaaaAAAaa

Update2:总结...我最终得到的最小功能:

FILE *fopenrwc(char*n) {FILE*f=fopen(n,"a");if(f)fclose(f),f=fopen(n,"r+");return f;}
or:
FILE *fopenrwc(char*n) {return fdopen(open(n,O_RDWR|O_CREAT,0666),"r+");}

【问题讨论】:

  • 为什么a+ 不适合你?
  • 请说明为什么“a+”不起作用。
  • @SouravGhosh "a+" 是我的第一选择,但在包含内容的文件中,fseek(0), write(buf)... 附加到文件末尾而不是开头。它没有附加 fseek 和 ftell 所说的内容。
  • 如果您在一台足够类似于 POSIX 的机器上能够使用 open(),请不要低估 fdopen() 的好处,它允许您使用带有选项的 open()您展示了然后创建一个文件流来使用该文件。
  • 如果您想要更精细的控件,例如O_EXCL,或专门的属性,例如O_DSYNCO_NOCTTY,甚至可以控制创建文件的权限,而不是默认的修改权限通过umask(),然后open() 加上fdopen() 实际上是唯一的方法。

标签: c fopen


【解决方案1】:

如果您查看fopen() 的手册页,则没有一个标准的开放模式字符串符合您的要求。

如果您在一台足够类似于 POSIX 的机器上能够使用 open(),请不要低估 fdopen() 的好处,它允许您使用 open() 与您显示的选项,然后创建使用该文件的文件流。

请注意,"rw+" 不是有效模式。如果你(不)走运,它会被视为r+

如果由于某种原因您不能使用fdopen(),您最好尝试r+,如果失败则使用w+;这会打开一个小漏洞窗口,有人可能会创建一个文件,然后您使用 w+ 选项破坏该文件 - 或创建一个符号链接,因此您最终会创建一个您不打算这样做的文件。

这是过去使用open() 所必需的方式;最初,你调用了open()——在之前有一个O_CREAT——如果失败了,那么你使用creat()。不过那是很久以前的事了——请参阅7th Edition UNIX Programmer's Manual Vol 2 中的“UNIX 编程”。

一般来说,使用access() 进行测试没有帮助。它留下了一个漏洞窗口,因为在使用access()open()(或fopen())之间存在一个TOCTOU——检查时间,使用时间——差距。这也是open()creat() 的问题,或者两次调用fopen()

如果您想要更精细的控件,例如O_EXCL,或专门的属性,例如O_DSYNCO_NOCTTY,甚至控制创建文件的权限,而不是umask() 修改的默认权限,那么open() 加上fdopen() 实际上是唯一的出路。

【讨论】:

    【解决方案2】:

    简单的fopen 无法直接满足您的要求。恕我直言,您最好的选择是首先使用低级别的open 创建文件,然后使用fdopen(如Jonathan Leffler 所建议)获得一个FILE *,然后可以与所有C 库一起使用IO函数:

    int fd =open("fname", O_RDWR | O_CREAT, 0666);
    FILE *fp = fdopen(fd, "r+");
    /* Ok, you can do what you want with fp */
    

    【讨论】: