fread / fwrite没有按预期工作

时间:2022-08-20 07:06:49

So I am trying to write a c file that has a student record database, once the file runs it is supposed to read student records from a binary file and add them to a linked list: the student struct looks like this :

所以我试着写一个有学生记录数据库的c文件,一旦文件运行它应该从二进制文件读取学生记录并将它们添加到链表:学生结构如下所示:

typedef struct student {
    char lname[10], initial, fname[10];
    unsigned long SID;
    float GPA;

    struct student* next; /* pointer to the next student record */   
} studentList;

I am using single linked lists for my data, and my code runs fine if I read and write the data with fscanf. However, once I started using fwrite and fread, everytime my program loads it would not load up the data from the text file correctly, when I check the binary file it seems it has data in it. Here is what I have for my load and write data functions:

我正在为我的数据使用单个链接列表,如果我使用fscanf读取和写入数据,我的代码运行正常。但是,一旦我开始使用fwrite和fread,每次我的程序加载它都不会正确加载文本文件中的数据,当我检查二进制文件时,它似乎有数据。这是我的加载和写入数据函数:

void printRecords() {
    FILE *fPointer = fopen("data.bin", "w");
    studentList *newStudent = head;
    while (newStudent != NULL) { /*Loop through linked list starting from head node*/
        fwrite(&newStudent, sizeof(newStudent), 1, fPointer);

        newStudent = newStudent->next;
    }
}

void loadRecords() {
    studentList *cStudent;
    FILE *fPointer = fopen("data.bin", "r");
    int counter = 0;
    int x = 0;
    int n = 0;
    while (n != 0) {
        printf("test\n");
        if (fPointer == NULL) {
            break;
        }
        cStudent = (studentList *)malloc(sizeof(studentList));
        n = fread(&cStudent, sizeof(cStudent), 1, fPointer);
        x = cStudent->GPA;
        printf("%d\n", x);
        if (feof(fPointer)) { break; }
        if (counter == 0) {
            head = cStudent;
            temp = (studentList *)malloc(sizeof(studentList));
            temp = cStudent;
            counter++;
        }

        temp->next = (studentList *)malloc(sizeof(studentList));
        temp->next = cStudent;
        temp = temp->next;
    }
    fclose(fPointer);
}

so what am I doing wrong as right now it does not read anything into my list, it seems like it writes but not sure if it even writes the correct data, I have spent a long time trying to figure this out and have been stuck on it for a while now, thanks in advance.

我现在做错了什么,因为它现在没有读到我的列表中的任何内容,它似乎写了但不确定它是否写出正确的数据,我花了很长时间试图解决这个问题并且一直困在现在好了一段时间,先谢谢了。

3 个解决方案

#1


1  

To read write to binary files in c.

在c中读取对二进制文件的写入。

FILE   *fPointer=fopen("data.bin","wb");  //to write file
FILE *fPointer=fopen("data.bin","rb");    //to read file

#2


1  

There are multiple problems with your code.

您的代码存在多个问题。

printRecords has problems:

printRecords有问题:

  • you should use binary mode.
  • 你应该使用二进制模式。
  • you write the contents of the pointer and some indeterminate contents instead of whet the pointer points to. This is actually undefined behavior.
  • 你写指针的内容和一些不确定的内容,而不是指针指向。这实际上是未定义的行为。
  • you forgot to close the file.
  • 你忘了关闭文件。
  • the value written to the file for the next member is meaningless. Writing the same records may produce different file contents for different runs.
  • 写入下一个成员的文件的值是没有意义的。写入相同的记录可能会为不同的运行生成不同的文件内容。

Here is a corrected version that returns the number of records written or -1 if the file could not be opened:

这是一个更正版本,返回写入的记录数,如果无法打开文件,则返回-1:

int printRecords(void) {
    FILE *fPointer = fopen("data.bin", "wb");
    studentList *sp;
    int n = 0;

    if (fPointer == NULL)
        return -1;

    /* Loop through linked list starting from head node */
    for (sp = head; sp != NULL; sp = sp->next) {
        n += fwrite(sp, sizeof(newStudent), 1, fPointer);
    }
    fclose(fPointer);
    return n;
}

loadRecords has even more problems:

loadRecords还有更多问题:

  • binary mode should be used too.
  • 也应该使用二进制模式。
  • the way you test for end of file is incorrect.
  • 测试文件结尾的方式不正确。
  • the way you link records does not work either.
  • 链接记录的方式也不起作用。

Here is a corrected version of loadRecords that returns the number of records read or -1 if the file could not be opened:

以下是loadRecords的更正版本,它返回读取的记录数,如果无法打开文件,则返回-1:

int loadRecords(void) {
    studentList student, *newsp, *sp;
    FILE *fPointer = fopen("data.bin", "rb");
    int n = 0;

    if (fPointer == NULL)
        return -1;

    while (fread(&student, sizeof(student), 1, fPointer) == 1) {
        n++;
        student.next = NULL;  // value read from file is meaningless
        newsp = malloc(sizeof(studentList));
        *newsp = student;
        if (head == NULL) {
            head = newsp;
        } else {
            /* append the new record to the list */
            for (sp = head; sp->next; sp = sp->next)
                continue;
            sp->next = newsp;
        }
    }
    fclose(fPointer);
    return n;
}

Be aware that storing binary data to the file system this way is not portable. The representation of integers and floats may differ from one platform to another, as well as alignment of the structure members, especially the next pointer which is useless in the file anyway. This file should only be read back on the same platform, with the same program that wrote it, making it a poor choice for backup or persistent storage.

请注意,以这种方式将二进制数据存储到文件系统是不可移植的。整数和浮点数的表示可能因平台而异,以及结构成员的对齐,尤其是无论如何在文件中无用的下一个指针。此文件只能在同一平台上回读,使用相同的程序编写它,使其成为备份或持久存储的不良选择。

#3


0  

There are problems in the file write function, mainly the data pointer and size:

文件写入功能存在问题,主要是数据指针和大小:

void printRecords(){
    FILE *fPointer = fopen("data.bin","wb");    // add "b" mode (MSVC)
    if (fPointer == NULL)                       // check file opened
        exit(1);                                // or report "Cannot open file"
    studentList *newStudent = head;
    while(newStudent !=NULL)
    {
        fwrite(newStudent, sizeof(*newStudent), 1, fPointer);   // remove the & and add a *
        newStudent = newStudent->next;
    }
    if (fclose(fPointer))                       // close the file
        exit(1);                                // or report "Failed to close file"
}

#1


1  

To read write to binary files in c.

在c中读取对二进制文件的写入。

FILE   *fPointer=fopen("data.bin","wb");  //to write file
FILE *fPointer=fopen("data.bin","rb");    //to read file

#2


1  

There are multiple problems with your code.

您的代码存在多个问题。

printRecords has problems:

printRecords有问题:

  • you should use binary mode.
  • 你应该使用二进制模式。
  • you write the contents of the pointer and some indeterminate contents instead of whet the pointer points to. This is actually undefined behavior.
  • 你写指针的内容和一些不确定的内容,而不是指针指向。这实际上是未定义的行为。
  • you forgot to close the file.
  • 你忘了关闭文件。
  • the value written to the file for the next member is meaningless. Writing the same records may produce different file contents for different runs.
  • 写入下一个成员的文件的值是没有意义的。写入相同的记录可能会为不同的运行生成不同的文件内容。

Here is a corrected version that returns the number of records written or -1 if the file could not be opened:

这是一个更正版本,返回写入的记录数,如果无法打开文件,则返回-1:

int printRecords(void) {
    FILE *fPointer = fopen("data.bin", "wb");
    studentList *sp;
    int n = 0;

    if (fPointer == NULL)
        return -1;

    /* Loop through linked list starting from head node */
    for (sp = head; sp != NULL; sp = sp->next) {
        n += fwrite(sp, sizeof(newStudent), 1, fPointer);
    }
    fclose(fPointer);
    return n;
}

loadRecords has even more problems:

loadRecords还有更多问题:

  • binary mode should be used too.
  • 也应该使用二进制模式。
  • the way you test for end of file is incorrect.
  • 测试文件结尾的方式不正确。
  • the way you link records does not work either.
  • 链接记录的方式也不起作用。

Here is a corrected version of loadRecords that returns the number of records read or -1 if the file could not be opened:

以下是loadRecords的更正版本,它返回读取的记录数,如果无法打开文件,则返回-1:

int loadRecords(void) {
    studentList student, *newsp, *sp;
    FILE *fPointer = fopen("data.bin", "rb");
    int n = 0;

    if (fPointer == NULL)
        return -1;

    while (fread(&student, sizeof(student), 1, fPointer) == 1) {
        n++;
        student.next = NULL;  // value read from file is meaningless
        newsp = malloc(sizeof(studentList));
        *newsp = student;
        if (head == NULL) {
            head = newsp;
        } else {
            /* append the new record to the list */
            for (sp = head; sp->next; sp = sp->next)
                continue;
            sp->next = newsp;
        }
    }
    fclose(fPointer);
    return n;
}

Be aware that storing binary data to the file system this way is not portable. The representation of integers and floats may differ from one platform to another, as well as alignment of the structure members, especially the next pointer which is useless in the file anyway. This file should only be read back on the same platform, with the same program that wrote it, making it a poor choice for backup or persistent storage.

请注意,以这种方式将二进制数据存储到文件系统是不可移植的。整数和浮点数的表示可能因平台而异,以及结构成员的对齐,尤其是无论如何在文件中无用的下一个指针。此文件只能在同一平台上回读,使用相同的程序编写它,使其成为备份或持久存储的不良选择。

#3


0  

There are problems in the file write function, mainly the data pointer and size:

文件写入功能存在问题,主要是数据指针和大小:

void printRecords(){
    FILE *fPointer = fopen("data.bin","wb");    // add "b" mode (MSVC)
    if (fPointer == NULL)                       // check file opened
        exit(1);                                // or report "Cannot open file"
    studentList *newStudent = head;
    while(newStudent !=NULL)
    {
        fwrite(newStudent, sizeof(*newStudent), 1, fPointer);   // remove the & and add a *
        newStudent = newStudent->next;
    }
    if (fclose(fPointer))                       // close the file
        exit(1);                                // or report "Failed to close file"
}