提问者:小点点

fread/fwrite未按预期工作


所以我正在尝试编写一个具有学生记录数据库的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;

我的数据使用单链表,如果我使用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);
}

所以我做错了什么,因为现在它没有向我的列表中读取任何内容,它似乎在写,但不确定它是否写了正确的数据,我花了很长时间试图弄清楚这一点,并且已经坚持了一段时间,提前感谢。


共3个答案

匿名用户

读写到c中的二进制文件。

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

匿名用户

您的代码存在多个问题。

printRecords有问题:

  • 您应该使用二进制模式。
  • 您写入指针的内容和一些不确定的内容,而不是指针指向的whet。这实际上是未定义的行为。
  • 您忘记关闭文件。
  • 下一个成员写入文件的值没有意义。编写相同的记录可能会为不同的运行产生不同的文件内容。

这是一个更正版本,如果无法打开文件,则返回写入的记录数或-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有更多的问题:

  • 也应该使用二进制模式。
  • 您测试文件末尾的方式不正确。
  • 链接记录的方式也不起作用。

这是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;
}

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

匿名用户

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

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"
}