在追加模式下,ftell()返回文件指针位置的初始值是什么?

4
我正在查看SO帖子fseek在打开文件时使用“a”(追加)模式时不起作用,我对于在“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);
}
2个回答

3

你问:

为什么指针最初在0位置?

在你提出的问题的一般性层面上,唯一可用的答案是这是你特定实现所做的选择。标准规定:

如果一个文件可以支持定位请求(例如磁盘文件,而不是终端),那么与流相关联的文件位置指示器将定位到该文件的开头(字符号0),除非文件以追加模式打开,在这种情况下,初始时文件位置指示器的位置是由实现定义的,它是位于文件开头还是结尾。

(C2011, 7.21.3/1)

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

在追加模式下是否有使用fseek的情况?

它的主要用途与仅以附加方式打开的文件无关。然而,我不准备说它没有任何用处,当然也不希望因为将这样的文件传递给它而出错。该问题表明您对文件位置的概念存在误解。除了当文件首次打开时,它(对于支持它的流)只是由对该流上的最后一次I/O操作产生的位置,其中 fseek() 是一种合法的I/O操作。

当然,在同时打开读取和追加的文件中,fseek() 的正常用法是完全合理的。


1

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

这似乎是一个实现特定的细节。我在C标准中没有找到关于以纯追加模式打开文件时初始文件偏移量的明确提及。

在追加模式下是否有使用fseek的情况?

在纯追加模式下,无法进行读取,因此fseek()似乎是无效的。根据7.21.5.3 The fopen function,第6段 C标准

使用追加模式(将'a'作为mode参数的第一个字符)打开文件会导致所有后续写入强制到当前的文件结尾,不管调用了多少次fseek函数。...

然而,根据第7段,以附加/更新模式"a+"打开时,调用fseek()可以用于定位当前文件指针进行读取:

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

因此,在附加/更新模式下从文件中读取需要使用fseek()来定位当前位置,以便在写入其他内容时将其定位到当前文件末尾之后。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接