Usage of fopen modes r, r+, w, w+, a and a+

Background

I did the following operations, but got an unexpected result.

  • Use fopen function to open a file.
  • Use fprintf function to write two integers to this file.
  • Use fscandf function to read the integers.
  • Got NULL.

After I have analysed the reason, I found it was related to fopen modes, so I am going to write this article to introduce the detalied difference between fopen modes r, r+, w, w+, a, a+.

Introduction

Prototype of fopen:


FILE *fopen(const char *restrict pathname, const char *restrict type);

The options for type parameter:

TypeDescriptionOpen(2) flags
r, rbopen for readingO_RDONLY
w, wbTruncate the file to 0 length, or created for writingO_WDONLY|O_CREAT|O_TRUNC
a, abAppend: Open for writing at the end of a file, or created for writingO_WDONLY|O_CREAT|O_APPEND
r+, rb+, r+bOpen for reading and writingO_RDWR
w+,wb+,w+bTruncate a file to 0, or open it for reading and writingO_RDWR|O_CREAT|O_TRUNC
a+,ab+, a+bOpens and creation for end-of-file reading and writingO_RDWR|O_CREAT|O_APPEND

Below is my code and understanding the above parameters by changing the parameters.

#include <stdio.h>

int main()
{
    FILE *fp = NULL;

    if ((fp = fopen("data.txt", "w+")) == NULL) {
	printf("open file error\n");
    }

    int a = 2, b = 3;
    int cnt = -1, cnt1 = -1;
    long pos = -1;

    fprintf(fp, "%d %d\n", a, b);
    //fseek(fp, 0, SEEK_SET);

    fscanf(fp, "%d %d", &amp;cnt, &amp;cnt1);

    pos = ftell(fp);
    printf("pos = %ld\n", pos);
    printf("%d %d\n", cnt, cnt1);
	
    fclose(fp);
    return 0;
}

Case 1: “w”

Modify the above code from “fp = fopen(“data.txt”, “w+”)” to “fp = fopen(“data.txt”, “w”)“.

Write only. If the file does not exist, it will be created automatically. And the cursor position is moved after the write.

Output:

$ ./a.out
pos = 4
-1 -1

Because “w” is only for write and the current position is 4 rather than 0, so we can’t read the a, b integers.

Case 2: “r”

Modify the above code from “fp = fopen(“data.txt”, “w+”)” to “fp = fopen(“data.txt”, “r”)“.

Read only. If the file does not exist at this time, it will not be created automatically and fopen will fail.

Output:

$ ./a.out
pos = 4
-1 -1

Even if we changed the type from “w” to “r”, we still can’t read the data because the current position is also 4.

We can use fseek to change the current position to 0 and read the data again.

Removed the annotation on “fseek(fp, 0, SEEK_SET);” in the above code.

Output:

pos = 3
2 3

Now, we can read the data because the current position is 0 before reading.

Case 3: “rw”

There is no such mode, this mode will fail to write.

Case 4: “r+” 和 “w+”

Modify the above code from “fp = fopen(“data.txt”, “w+”)” to “fp = fopen(“data.txt”, “r+”)” or no changes.

Output:

$ ./a.out
pos = 4
-1 -1

Though “r+” and “w+” mean read and write, they also can’t read the data because the current position is not 0.

Note:

  • If you want to open a binary file, you need to add “b” in type parameter. If not, you don’t need to add “b”.
  • The addition of a “+” indicates that both “r+” and “w+” are read-write, and the cursor will move backward. So if you want to fetch data, you need to use the fseek() function to point the cursor to the starting position.Fseek (fp, 0, SEEK_SET) after fprintf.

Related articles:

[Solution]what is the format for printf to print unsigned char itself? 

Any feedbacks are welcome.

Share this article to your social media
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments