2013-02-14 94 views
5

我正在打开一些正在打开,阅读和修改文本文件的代码。快速(简体)的例子是:使用“r +”在fopen上windows vs linux

#include <stdio.h> 
int main() 
{ 
    FILE * fp = fopen("test.txt", "r+"); 
    char line[100] = {'\0'}; 
    int count = 0; 
    int ret_code = 0; 
    while(!feof(fp)){ 
     fgets(line, 100, fp); 
     // do some processing on line... 
     count++; 
     if(count == 4) { 
      ret_code = fprintf(fp, "replaced this line\n"); 
      printf("ret code was %d\n", ret_code); 
      perror("Error was: "); 
     } 
    } 
    fclose(fp); 
    return 0; 
} 

现在在Linux上,与海湾合作委员会(4.6.2)运行此代码编译,并修改文件的5日线。使用Visual C++ 2010编译的Windows7上运行的相同代码运行并声称已成功(报告返回码为19个字符,而perror表示“无错误”),但未能替换该行。

在Linux上我的文件具有完全的权限:

-rw-rw-rw- 1 mike users 191 Feb 14 10:11 test.txt 

而据我可以告诉它是相同的Windows:

的test.txt(右键) - >属性 - >安全
检查“允许”为读取&写入用户,系统和管理员。

我在Windows上使用MinGW的gcc获得了相同的结果,所以我知道它不是一个Visual C++“功能”。

我失去了一些东西明显,或者是我没有得到任何错误的情况,也没有输出只使用r+fopen()在Windows上的无证“功能”?


编辑:
似乎即使在Microsoft's site他们说 “R +” 应该打开阅读书面方式。他们还提出了这样一个字条:

当“R +”,“W +”,或“+”访问类型指定,阅读和写作都被允许(该文件被认为是开放的“更新”) 。但是,当您在读取和写入之间切换时,必须存在干预fflush,fsetpos,fseek或倒带操作。如果需要,可以为fsetpos或fseek操作指定当前位置。

所以,我想:

 ... 
     if(count == 4) { 
      fflush(fp); 
      ret_code = fprintf(fp, "replaced this line\n"); 
      fflush(fp); 
      printf("ret code was %d\n", ret_code); 
      ... 

无济于事。

+0

您是否在写入操作之后尝试使用'fflush'刷新流? – Cyclonecode 2013-02-14 15:47:36

+3

我不确定这是否是问题,但您可能需要在文件 – Hasturkun 2013-02-14 15:48:47

+0

@KristerAndersson - yup之间切换读取和写入时调用'fseek',只是更新以澄清我在MSDN网站上看到说你的注释应该更新'f ()'之一的流,所以我在写入之前和之后尝试了'fflush()',但没有骰子。 – Mike 2013-02-14 15:51:46

回答

3

按照Linux man page for fopen()

读取和写入可被以任何顺序的读/写数据流混合。 请注意,ANSI C要求文件定位功能在输出和输入之间插入 ,除非输入操作遇到 文件结束。 (如果不满足这个条件,则允许读取 返回除最近写入之外的写入结果。)因此,它是一个很好的做法(并且实际上有时在Linux下有必要)将 设置为fseek(3)或fgetpos(3)在这样的流上的写入和读取操作 之间的操作。此操作可能是一个明显的无操作(如 FSEEK(...,0L,SEEK_CUR)要求其同步的副作用。

所以,你应该始终调用fseek()(如如。fseek(..., 0, SEEK_CUR))在从文件读取和写入之间切换时。

+1

这是问题所在,这就是我阅读MSDN文档而不是手册页所得到的结果。 :) 谢谢。 – Mike 2013-02-14 16:08:16

+0

请注意,来自MSDN(VS 2012)的最新文档已更新:http://msdn.microsoft.com/en-us/library/yeby3zcb.aspx – 2013-02-14 16:16:35

+0

@MichaelBurr - 好点,这不是最最近的文档,我应该更新我的书签,过了一段时间,因为我去过那里。 – Mike 2013-02-14 16:22:54

3

在输入之后执行输出之前,fflush()不是什么好事 - 您需要执行查找操作。类似:

fseek(fp, ftell(fp), SEEK_SET); // not fflush(fp); 

从C99标准(7.19.5.3/6“则fopen functoin):

当一个文件被打开与更新模式( '+' 作为第二或第三 字符在上面的模式参数值列表中),输入和 输出都可以在关联的数据流上执行,但输出 不应直接跟随输入,而不需要中间调用fflush函数的 或文件定位功能(fseek, fsetpos或倒带),并且输入不应该直接跟在输出 之后,除非 输入操作遇到文件结束,否则不会调用文件定位功能。

+0

这很有趣,你说“fflush()不是什么好事”,但是你引用的C99片段说:“没有对fflush函数或文件定位函数的干预调用。所以,就在那里,它表示“fflush()'或'fseek()'/其他定位函数。 – Mike 2013-02-14 16:24:28

+2

这是输出后输入。你的问题是在执行输入后输出,这需要一个介入文件定位调用(或EOF)。我会说,为了让所有的条件都能在你的脑海中畅通无阻,阅读起来会很棘手 - 一张桌子会更好。 – 2013-02-14 16:38:28

+0

+1得到它,这使得订购很重要的原因。感谢您的意见。 – Mike 2013-02-14 19:21:13