Reading a File in C: different behavior for “r” an

2019-08-30 10:22发布

问题:

I want to open a file, read its contents, and then append a line to the file. I thought I should use the "a+" flag for the task.

I have a function which opens a file and returns a pointer to this file.

FILE* open_weekly_disk_file(char* filename){
    FILE* weekly_log;

    weekly_log = fopen(filename, "a+");
    //weekly_log = fopen(filename, "r");

    if(! weekly_log){
        printf("The attempt to open the weekly log failed!\n");
        return NULL;
    } else{
        return weekly_log;
    }
}

Then I have a function which calls the function above and uses scanf to read contents from the file:

void sample_function(char* filename){
    FILE* log;
    char token[100], current_read[100];
    int limit;

    log = opened_weekly_disk_file(filename);
    // The problem happens here
    for(limit=0; limit < TOKEN_NUMBER; limit++){
        if(fscanf(log, "%s%s", &token, &current_read) == 2){
            printf("%s %s\n", token, current_read);
        }
    }
    ...
}

This code works when I use:

weekly_log = fopen(filename, "r");

But does not work when I change the "r" flag to "a+". I get a Segmentation fault right before the for loop.

回答1:

That is because the mode spec "a" opens a file for appending, with the file pointer at the end. If you try to read from here, there is no data since the file pointer is at EOF. You should open with "r+" for reading and writing. If you read the whole file before writing, then the file pointer will be correctly positioned to append when you write more data.

If this is not enough, please explore ftell() and fseek() functions.



回答2:

from this SO QA

from the man page: a+

Open for reading and appending (writing at end of file). The file is created if it does not exist. The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file.

Answer:

There is just one pointer which initially is at the start of the file but when a write operation is attempted it is moved to the end of the file. You can reposition it using fseek or rewind anywhere in the file for reading, but writing operations will move it back to the end of file.

So, the problem is not the fact that the file is opened in append mode, because it is not, as far as reading from it is concerned.

The problem lies in what your code does in those three dots

log = opened_weekly_disk_file(filename);
    ...

The code quite probably writes to the file, making the file cursor move to the end of it before the reading occurs.