简体   繁体   中英

fread/fwrite a struct to/from a file in C

I'm having troubles using the fread/fwrite functions to read and write structures to a file. First of all, text written by fwrite is unreadable for me, but from what I see, it is intended to work like this. Is there a way to make it plain text, or it has to be like that?

The other problem is that when I try to read from that file using the fread function, few last elements aren't read.

Further, I'll need this piece of code to sort, directly on the disk, data from a file. Usage of fread/fwrite is compulsory..

#include <stdio.h>

typedef struct camesi {
    char camasa[33];
    char culoare[33];
    int marime;
    char material[33];
} cam;

int main() {

    FILE *f, *f2;
    int i, j, n;
    cam a, b, c;

    n = 13;

    f  = fopen ("new.txt", "w+");
    f2 = fopen ("asd.txt", "r");
    rewind (f2);

    for (i = 0; i < n; i++) {
        fscanf (f2, "%s%s%d%s", c.camasa, c.culoare, &c.marime, c.material);
        printf ("%s\t%s\t%d\t%s\n", c.camasa, c.culoare, c.marime, c.material);
        fwrite (&c, sizeof (cam), 1, f);
    }

    printf ("\n----------------------------------------\n\n");

    rewind (f);

    for (i = 0; i < n; i++) {
        fread (&c, sizeof (cam), 1, f);
        printf ("%s\t%s\t%d\t%s\n", c.camasa, c.culoare, c.marime, c.material);
    }

return 0; }

This is the output to console:

asdf1   blue    45      skin
asdf2   green   43      skin
asdf3   white   49      skin
asdf4   red     47      skin
asdf5   yellow  54      skin
asdf6   purple  13      skin
asdf7   magenta 74      skin
asdf8   pink    41      skin
asdf9   black   97      skin
asdf10  gray    85      skin
asdf11  orange  26      skin
asdf12  violet  64      skin
asdf13  brown   11      skin

----------------------------------------

asdf1   blue    45      skin
asdf2   green   43      skin
asdf3   white   49      skin
asdf4   red     47      skin
asdf5   yellow  54      skin
asdf6   purple  13      skin
asdf7   magenta 74      skin
asdf8   pink    41      skin
asdf9   black   97      skin
asdf10  gray    85      skin
asdf11  orange  85      skin
asdf11  orange  85      skin
asdf11  orange  85      skin

The first half is the data read from a manually created *.txt file.

The other half is the data read from a file created with the program, using fwrite function.

Content of the original *.txt file:

asdf1   blue    45  skin
asdf2   green   43  skin
asdf3   white   49  skin
asdf4   red 47  skin
asdf5   yellow  54  skin
asdf6   purple  13  skin
asdf7   magenta 74  skin
asdf8   pink    41  skin
asdf9   black   97  skin
asdf10  gray    85  skin
asdf11  orange  26  skin
asdf12  violet  64  skin
asdf13  brown   11  skin

Content of the file created with fwrite function:

asdf1   €M o  ёю(  Ђ(wїдЂ‚юяяяblue           M             -   skin M `M      А&M €ю( HЯПt  M asdf2   €M o  ёю(  Ђ(wїдЂ‚юяяяgreen          M             +   skin M `M      А&M €ю( HЯПt  M asdf3   €M o  ёю(  Ђ(wїдЂ‚юяяяwhite          M             1   skin M `M      А&M €ю( HЯПt  M asdf4   €M o  ёю(  Ђ(wїдЂ‚юяяяred e          M             /   skin M `M      А&M €ю( HЯПt  M asdf5   €M o  ёю(  Ђ(wїдЂ‚юяяяyellow         M             6   skin M `M      А&M €ю( HЯПt  M asdf6   €M o  ёю(  Ђ(wїдЂ‚юяяяpurple         M             
   skin M `M      А&M €ю( HЯПt  M asdf7   €M o  ёю(  Ђ(wїдЂ‚юяяяmagenta        M             J   skin M `M      А&M €ю( HЯПt  M asdf8   €M o  ёю(  Ђ(wїдЂ‚юяяяpink ta        M             )   skin M `M      А&M €ю( HЯПt  M asdf9   €M o  ёю(  Ђ(wїдЂ‚юяяяblack a        M             a   skin M `M      А&M €ю( HЯПt  M asdf10  €M o  ёю(  Ђ(wїдЂ‚юяяяgray  a        M             U   skin M `M      А&M €ю( HЯПt  M asdf11  €M o  ёю(  Ђ(wїдЂ‚юяяяorange         M                skin M `M      А&M €ю( HЯПt  M asdf12  €M o  ёю(  Ђ(wїдЂ‚юяяяviolet         M             @   skin M `M      А&M €ю( HЯПt  M asdf13  €M o  ёю(  Ђ(wїдЂ‚юяяяbrown          M                skin M `M      А&M €ю( HЯПt  M 
asdf11  orange  26  skin   

Windows可能会将txt文件中的26视为EOF

Is there a way to make it plain text, or it has to be like that?

Yes, it has to be like that because when it was written, the file was filled with the data that was in memory. So it's always like this ie combination of readable and unreadable characters.

In order to understand the behavior of fread/fwrite i will take the example from your output

asdf1   blue    45      skin$asdf1   blue    45      skin$asdf1   blue    45      skin$asdf1   blue    45      skin$asdf1   blue    45      skin$asdf1   blue    45      skin$asdf1   blue    45      skin$

Now let suppose that the above code is in memory such that asdf1 blue 45 skin is a structure currently in memory. '$' is just a seperator to represent 7 structures residing in memory. Now if you want to read data from a file into a structure using fread, then the ideal situation is that the file the file was written using fwrite by writing each structure one by one, without any extra byte between them. Only then it can easily be read using fread().

To demonstrate this, here is a simple program that first fill 5 struct objects and then write them onto a file using fwrite. Then it again read those written structures from the file and then fill the C structures with that data.

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#define MAX 5

struct camesi {
    char camasa[33];
    char culoare[33];
    int marime;
    char material[33];
} myStruct;

int main()
{
    int i = 0;
    FILE *file = NULL;

    //Fill a structure with values
    memset(&myStruct, 0, sizeof(myStruct));
    memcpy(myStruct.camasa, "asdf1", 5);
    memcpy(myStruct.culoare, "blue", 4);
    myStruct.marime = 45;
    memcpy(myStruct.material, "skin", 4);

    //Open the file to write
    if ((file = fopen("test.txt", "w+")) == NULL) {
        printf("Error opening file to write\n");
        return -1;
    }

    for (i = 0; i < MAX; i++)
        fwrite(&myStruct, sizeof(myStruct), 1, file);

    fclose(file);

    //Open the file for read
    if ((file = fopen("test.txt", "r")) == NULL) {
        printf("Error opening file for read\n");
        return -1;
    }

    //Clear the myStruct from previous values
    memset(&myStruct, 0, sizeof(myStruct));

    //Read and display
    for (i = 0; i < MAX; i++)
    {
        fread(&myStruct, sizeof(myStruct), 1, file);
        printf("%s\t%s\t%d\t%s\n", myStruct.camasa, myStruct.culoare, myStruct.marime, myStruct.material);

        //Clear the myStruct from previous value as we will read again in same object in next iteration
        memset(&myStruct, 0, sizeof(myStruct));
    }

    fclose(file);

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM