2016-04-29 41 views
0

我想:如果它不存在,要创建Ç的fopen模式读+写+创建

  1. 文件,not overwritten if it does
  2. 读写和fseek过的位置我想

,我无法找到有效的方式 - “W +”, “RW”, “名胜世界+”, “R + B”, “W + B” “a +”还是什么?

性能良好的基本水平 'open' 是:

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

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

更新:澄清为何例如 “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+");} 
+1

为什么'a +'不适合你? –

+0

请说明为什么“a +”不起作用。 – Leandros

+0

@SouravGhosh“a +”是我的第一选择,但在包含内容的文件中,fseek(0),write(buf)...追加到文件末尾而不是开始。它没有附加fseek和ftell所说的话。 – MetNP

回答

2

如果您查看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()进行测试并没有帮助。由于存在TOCTOU - 检查时间,使用时间 - 在使用access()open()(或fopen())之间的差距,它留下了一个漏洞窗口。这也是open()creat()的问题,或者是fopen()的两个呼叫。

如果你想更精细的控制,如O_EXCL,或专门性质,如O_DSYNCO_NOCTTY,或者甚至超过上不是默认创建的文件的权限控制由umask()改性,然后open()fdopen()实际上是在唯一的办法就是去。

3

没有用简单的fopen直接满足您的要求。恕我直言,你最好的选择是先用一个低的水平open创建该文件,然后使用fdopen(由乔纳森·莱弗勒所建议)来获取然后可以与所有的C库IO函数使用FILE *

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