C fopen模式读+写+创建

C fopen mode read+write+create

我要:

  1. file to be created if it does not exist, not overwritten if it does.
  2. to read and write and fseek where ever I want

我找不到有效模式 — "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 不写在它应该写的地方。 "a+" 将始终追加,无论 fseek 设置什么...... "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

更新 2:总结...我最终得到的最少功能:

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+");}

没有直接的方法可以通过简单的 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 */

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

如果您使用的机器足够 POSIX 能够使用 open(), don't underestimate the benefits of fdopen() 这将允许您将 open() 与您显示的选项一起使用,然后创建一个文件流以使用该文件。

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

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

这是以前使用 open() 所必需的方式;最初,您调用了 open() — 在出现 O_CREAT 之前的几天 — 如果失败了,那么您使用了 creat() instead. That's a long time ago, though — see 'UNIX Programming' in 7th Edition UNIX Programmer's Manual Vol 2.

通常,使用 access() 进行测试没有帮助。它留下了一个 window 的漏洞,因为在 access()open()(或 fopen())的使用之间存在 TOCTOU — 检查时间,使用时间 — 差距。这也是 open()creat() 或两次调用 fopen().

的问题

如果您想要更精细的控制,例如 O_EXCL,或特定的属性,例如 O_DSYNCO_NOCTTY,甚至控制创建的文件的权限,而不是默认由 umask() 修改,然后 open() 加上 fdopen() 实际上是唯一的方法。