cfile-handlingfseekftell

initial value of file pointer position returned by ftell() in append mode


I was looking at SO post fseek does not work when file is opened in "a" (append) mode and I got a doubt regarding initial value of file pointer returned by ftell() when we open the file in "a" mode. I tried below code with file1.txt containing data "Hello Welcome" and printed the position of the pointer at various places. Initially ftell() will return position 0. After append, ftell() will return the last position. If we do fseek() file pointer gets changed and in this case I moved back to 0 position. In append mode, we cannot read data. Why the pointer is in 0 position initially? Also is there any use of fseek in append mode?

#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);
}

Solution

  • You ask

    Why the pointer is in 0 position initially?

    The only answer available at the level of generality at which you're asking as that it is a choice made by your particular implementation. The standard says:

    If a file can support positioning requests (such as a disk file, as opposed to a terminal), then a file position indicator associated with the stream is positioned at the start (character number zero) of the file, unless the file is opened with append mode in which case it is implementation-defined whether the file position indicator is initially positioned at the beginning or the end of the file.

    (C2011, 7.21.3/1)

    Thus, implementations have the alternative of initially setting the position to the start of the file or to its end for files opened in append mode. The former is consistent with the behavior when opening the file in any other mode, and reflects the position at which the next read would occur (for append modes that permit reading, such as "a+"); the latter reflects the position at which the first write would be performed. I would favor the former, myself, since you cannot rely on the file position of a file open in append mode to reflect the position of the next write anyway (the position could always be changed via fseek().

    Also is there any use of fseek in append mode?

    Its primary use is not relevant to files open in append-only mode. I'm not prepared to say that it has no use, however, and I certainly wouldn't want it to error out just because such a file is passed to it. The question suggests that you have the wrong conception of the file position. Other than when a file is first opened, it is (for streams that support it) simply the location resulting from the last I/O operation on that stream, where fseek() is a bona fide I/O operation.

    Of course, fseek() is perfectly sensible in its normal use for files open for both reading and appending.