【问题标题】:Why R/W transition mid-file in rb+ mode fails unless I use fseek(fp,0,SEEK_CUR)?Why it works at end of file?为什么 rb+ 模式下的 R/W 转换中间文件会失败,除非我使用 fseek(fp,0,SEEK_CUR)?为什么它在文件末尾有效?
【发布时间】:2013-05-24 05:32:34
【问题描述】:

我从来没有意识到这一点。我很可能下意识地认为这是一个很难的事实,即我可以在现有文件的读写之间转换打开它的更新模式,就像那样。但是关于 SO(1 的两个问题,2) 让我产生了怀疑,我决定尝试一下。这是我的发现:

在第一个程序prog1中,我处理一个文件source.txt,它只有致命武器行。我使用@阅读了第一个世界致命 987654325@ 并打算在那之后写“musket”,期望得到致命的火枪。但是它根本失败,我仍然得到原始内容致命武器 在写操作结束时。但是在第一个程序中,如果我插入行 fseek(fp,0,SEEK_CUR),写操作工作正常,我得到 Lethal musket。我注意到 fseek(fp,0,SEEK_CUR)除了打电话fseek()之外没有其他任何目的,因为根本没有网络搜索。

但是在第二个程序中,prog2,同样的场景不需要那个fseek(fp,0,SEEK_CUR) 语句。确切地说,在第二个程序中,与在第一个程序中读取文件中间相反,这里我读取到文件末尾,然后开始写入。这里即使不使用fseek(fp,0,SEEK_CUR)也写入成功,我得到了想要的内容致命武器销售

问题:为什么我们不能从文件中间的read 转换到write 模式,fseek(fp,0,SEEK_CUR) 有什么不同让它工作?同时,如果我们读取到文件末尾并在那里写入,为什么同样的转换工作没有任何大惊小怪?为什么在第二种情况下不需要fseek(fp,0,SEEK_CUR)?我使用fseek(fp,0,SEEK_CUR) 来使第一个程序中的写入成功有多大可取之处?还有更好的选择吗?

关于 SO 的两个问题似乎在某种程度上解决了同一个问题,但由于它们更多地基于寻求对文本/书籍摘录的解释,因此面向它们的答案似乎并没有解决我打算知道的问题准确地说。

//PROG1

#include <stdio.h>

int main ()
{
    FILE *fp=fopen("D:\\source.txt","r+");
    char arr[20],brr[50];
    fscanf(fp,"%s",arr);
    printf("String is %s\n",arr);
    //fseek(fp,0,SEEK_CUR);  //Doesn't work without it
    fprintf(fp," musket");
    rewind(fp);
    fgets(brr,50,fp);
    printf("New string is %s",brr);
    fclose(fp);
}

输出:

1) 没有fseek() -- 致命武器

2) 使用fseek() -- 致命步枪

//PROG2    

#include <stdio.h>

int main ()
{
    FILE *fp=fopen("D:\\source.txt","r+");
    char arr[20],brr[50];
    fgets(arr,20,fp);
    printf("Initial line is %s\n",arr);
    fprintf(fp," sale"); //writes to end of file
    rewind(fp);
    printf("New string is %s",fgets(brr,50,fp));
    fclose(fp);
}

不带 fseek() 的输出: -- Lethal weapon sale

【问题讨论】:

  • mode 'b' 是二进制模式,通常使用fread 读取,fwrite 写入`。我尝试了您的代码,但行为不同
  • @MYMNeo 因为我没有使用数字,所以二进制模式在这里不是问题。我仍然同意最好使用文本模式来说明我的观点。编辑它。谢谢指出。顺便说一句,什么是您计算机中的行为吗?
  • @MYMNeo 我必须指出,fread 在从文件中读取字符串时并不是很有帮助,因为您必须自己附加 Null 字符,这与 fscanf() 不同
  • PROG1,没有fseek也是致命步枪
  • @MYMNeo 我仔细检查了它。在我的计算机上没有fseek(),它仍然是致命武器,它似乎与其他两个问题及其链接所说的一致。

标签: c buffer flush fseek


【解决方案1】:

实际上,它看起来像是您的 libc 实现中的一个错误。 文件 I/O 流通常是对由 OS 内核实现的基于文件描述符的二进制 I/O 的 libc 抽象。因此,任何奇怪的行为都应归因于您特定的 libc 怪癖。

由于您显然使用的是 Windows,这可能是您的问题的根源。你使用的是什么编译器? GCC 4.6.1 和 glibc-2.13 在 Ubuntu 11.10 上没有这样的问题。

【讨论】:

  • 我在 windows 上使用 CodeBlocks/gcc。
  • 引用cplusplusreference"For files open for update (those which include a "+" sign), on which both input and output operations are allowed, the stream should be flushed (fflush) or repositioned (fseek, fsetpos, rewind) between either a writing operation followed by a reading operation or a reading operation which did not reach the end-of-file followed by a writing operation."
猜你喜欢
  • 2018-04-25
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 2020-09-18
相关资源
最近更新 更多