4

当文件以“a”(追加)模式打开时,我正在查看 SO post fseek does not work,当我们以“a”模式打开文件时,我对 ftell() 返回的文件指针的初始值有疑问。我使用包含数据“Hello Welcome”的 file1.txt 尝试了下面的代码,并在各个位置打印了指针的位置。最初 ftell() 将返回位置 0。追加后, ftell() 将返回最后一个位置。如果我们做 fseek() 文件指针被改变,在这种情况下我移回 0 位置。在附加模式下,我们无法读取数据。为什么指针最初处于 0 位置?还有在附加模式下使用 fseek 吗?

#include<stdio.h>
#include <string.h>
#include <errno.h>

#define MAX_BUF_SIZE 50

void readString(char* buffer,int maxSize)
{
    fgets(buffer,maxSize,stdin);
    // Note that if data is empty, strtok does not work. Use the other method instead.
    strtok(buffer,"\n");
}

extern int errno;

int main()
{
    FILE *fp1;
    char data[50];
    fp1=fopen("file1.txt","a");
    if(fp1==NULL)
    {
        // Print the error message
        fprintf(stderr,"%s\n",strerror(errno));
    }
    printf("Initial File pointer position in \"a\" mode = %ld\n",ftell(fp1));

    /* Initial file pointer position is 0 even in append mode
    As soon as data is write, FP points to the end.*/

    // Write some data at the end of the file only
    printf("\nEnter some data to be written to the file\n");
    readString(data,MAX_BUF_SIZE);
    // The data will be appended
    fputs(data,fp1);

    // File pointer points to the end after write operation
    printf("File pointer position after write operation in append mode = %ld\n",ftell(fp1));

    fseek(fp1,0,SEEK_SET);
    printf("File pointer position after fseek in append mode = %ld\n",ftell(fp1));

    return(0);
}
4

2 回答 2

3

你问

为什么指针最初处于 0 位置?

在您要求的一般性级别上唯一可用的答案,因为它是您的特定实现做出的选择。标准说:

如果文件可以支持定位请求(例如磁盘文件,而不是终端),则与流相关联的文件位置指示符位于文件的开头(字符编号为零),除非文件以追加模式在这种情况下,文件位置指示符最初定位在文件的开头还是结尾是由实现定义的。

( C2011, 7.21.3/1 )

因此,对于以附加模式打开的文件,实现可以选择将位置初始设置为文件的开头或结尾。前者与在任何其他模式下打开文件时的行为一致,并反映了下一次读取将发生的位置(对于允许读取的附加模式,例如“a+”);后者反映了将执行第一次写入的位置。我自己更喜欢前者,因为你不能依赖以附加模式打开的文件的文件位置来反映下一次写入的位置(位置总是可以通过fseek().

还有在附加模式下使用 fseek 吗?

它的主要用途与以仅附加模式打开的文件无关。但是,我不准备说它没有用,而且我当然不希望它仅仅因为这样的文件被传递给它而出错。该问题表明您对文件位置的概念有误。除了第一次打开文件时,它(对于支持它的流)只是该流上最后一次 I/O 操作产生的位置,这里fseek()真正的I/O 操作。

当然,fseek()对于为读取和附加而打开的文件的正常使用,它是完全明智的。

于 2017-10-23T15:59:15.420 回答
1

为什么指针最初处于 0 位置?

这似乎是特定于实现的细节。我在 C 标准中找不到特别提到以纯附加模式打开的文件的初始文件偏移量的参考。

还有在附加模式下使用 fseek 吗?

在纯附加模式下,无法读取,fseek()似乎实际上是无用的。每7.21.5.3fopen功能, C 标准的第 6 段:

以附加模式('a'作为参数中的第一个字符mode)打开文件会导致所有后续对该文件的写入都被强制到当前的文件结尾,而不管对fseek函数的干预调用。...

但是,根据第 7 段,以追加/更新模式打开"a+",调用fseek()可用于定位当前文件指针以供读取:

当以更新模式打开文件时('+'作为上述mode参数值列表中的第二个或第三个字符),可以在关联的流上执行输入和输出。...

因此,fseek()必要以追加/更新模式从文件中读取,以便在写入当前文件结尾以外的内容后定位当前位置。

于 2017-10-23T15:38:23.757 回答