C fopen模式读取+写入+创建

时间:2016-04-29 05:51:57

标签: c fopen

我想:

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

我无法找到有效的模式 - " w +"," rw" " RWB +" " R + B" " W + B" " +"或者什么?

基本级' open'表现良好的是:

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

但我想知道fopen alternative。 我试过的每个模式字母[w,r,a,+]组合都会覆盖内容,或者fseek-fwrite不会写入应该的位置。 " +"无论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

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

2 个答案:

答案 0 :(得分:3)

使用简单的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 */

答案 1 :(得分:2)

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

如果你在类似POSIX的机器上使用open(),请不要低估fdopen()的好处,这样可以让open()使用"rw+"您显示的选项,然后创建文件流以使用该文件。

请注意,r+不是有效模式。如果您(非)幸运,则将其视为fdopen()

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

这是以前使用open()所必需的方式;最初,您在O_CREAT之前的几天内调用了access() - 如果失败了,那么您使用的是creat()。这是很久以前的事了 - 请参阅7th Edition UNIX Programmer's Manual Vol 2中的“UNIX编程”。

通常,使用access()进行测试无济于事。它留下了一个漏洞窗口,因为有一个TOCTOU - 检查时间,使用时间 - 使用open()fopen()(或open())之间的差距。这也是creat()fopen()或两次调用O_EXCL的问题。

如果您想要更精细的控件(例如O_DSYNC)或专用属性(例如O_NOCTTYopen()),或者甚至可以控制创建文件的权限(默认值除外)由umask()修改,然后fdopen()加上index实际上是唯一的出路。