简体   繁体   中英

Writing data from a linked list to a binary file using fwrite.

I do not know how to approach this task.

I specifically have to use fwrite, but my problem is that I do not know how to write different file types(char[], int, double) into a single line in the binary file, increment it, then write the next lot of data from the linked list increment it..... and so on.

The code below writes data from a linked list(Data) into text file, goes to next line and repeats the process until the last element of the list has been written to the text file.

I need to code a function that has the same principles but writes the data from the linked list into an binary file using fwrite. Any ideas guys?

void WriteTextFile(ListDataType *Data, int numEl)
{
    FILE *textfile;

    char name[50];

    printf("\n\nWhat would you like to call the text file in which the data will be stored?\nNB remember to add \".txt\" after your chosen name!!!\nENTER NAME NOW>>");
    scanf("%s", name);

    textfile = fopen(name, "w+");

    do
    {
        fprintf(textfile, "%s %d %d %.2lf %.2lf %.2lf %.2lf\n", Data->component.name, Data->component.int1, Data->component.int2, Data->component.double1, Data->double2, Data->double3, Data->double4 );
        Data = Data->nextPtr;
    }while(Data != NULL);

    fclose(textfile);
}

you'd want to do something like :

fwrite (Data , sizeof(ListDataType), 1, fileHandle);

this will write sizeof(ListDataType) bytes starting from wherever Data points. If your Data object has any pointers in it - you'd need to define a new struct, copy the values to that and then write the new struct.

if you cannot define a max length for the dynamic string then you could define a struct that includes the string length - write the struct, then the string - that way you'll know how many bytes to read back. Either way a struct is the nicest way to read and write to a bin file.

Ok - an edit with examples ...

if you define your component structure like :

    typedef struct Component_Struct
    {
        int int1;
        int int2;
        double double1;
        double double2;
        double double3;
        double double4;
        int nameLen;
        char* name;
    }
    COMPONENT, *LPCOMPONENT;

Note the extra nameLen - fill this value when you assign the values to the structure.

then in your write function :

      FILE * pFile;
      pFile = fopen ("myfile.bin", "wb");

      do
      {
          fwrite(Data->Component, sizeof(COMPONENT)-sizeof(char*), 1, pFile)
          fwrite(Data->Component.name, sizeof(char), Data->Component.nameLen, pFile)
        Data = Data->nextPtr;
      }
      while(Data !=NULL);


      fclose (pFile);

Since you have one item of variable length data (a dynamically allocated string pointer) you have to decide how you want to manage it in a binary file. You can set aside a fixed length of space for the name within the structure in your output. Or you can write a zero-terminated string and manage it that way. I'll choose the second case since it is more in line with the dynamic string.

This is a bit verbose since the nature of the structure hasn't been given in the problem statement. So the following will work with structure elements in arbitrary order.

void WriteBinaryFile(ListDataType *Data, int numEl)
{
    FILE *bin_file;

    char name[50];

    printf("\n\nWhat would you like to call the binary file in which the data will be stored?\n"
    printf("NB remember to add \".txt\" after your chosen name!!!\nENTER NAME NOW>>");
    scanf("%s", name);

    bin_file = fopen(name, "wb+");

    do
    {
        //NOTE: include terminating zero in the string output; assumes single-byte chars
        fwrite(Data->component.name, strlen(Data->component.name)+1, 1, bin_file);
        fwrite(&Data->component.int1, sizeof(Data->component.int1), 1, bin_file);
        fwrite(&Data->component.int2, sizeof(Data->component.int2), 1, bin_file);
        fwrite(&Data->component.double1, sizeof(Data->component.double1), 1, bin_file);
        fwrite(&Data->component.double2, sizeof(Data->component.double2), 1, bin_file);
        fwrite(&Data->component.double3, sizeof(Data->component.double3), 1, bin_file);
        fwrite(&Data->component.double4, sizeof(Data->component.double4), 1, bin_file);
        Data = Data->nextPtr;
    } while(Data != NULL);

    fclose(bin_file);
}

If a program needs to read it back, it would start by reading in a name and read characters until it finds a 0 . Then it would read the other elements per their data types. That process would be repeated for each structure written. This isn't necessarily portable, though. You have to be careful about size of int times, etc.

you should write different components differently, check samples:

fwrite(Data->stringcomponent, strlen(Data->stringcomponent)+1, 1, binaryfile); // writes 1 string
fwrite(&Data->doublecomponent, sizeof(double), 1, binaryfile); // writes 1 double
fwrite(&Data->intcomponent, sizeof(int), 1, binaryfile); // writes 1 int

so, instead of single fprintf you will have multiple fwrites for different data, note different kinds of length calculations (strlen+1 or sizeof) and whether you have to add & or not

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