fread / fwrite没有按预期工作

时间:2015-12-09 10:18:29

标签: c fwrite fread

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

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 个答案:

答案 0 :(得分:1)

read write to binary files in c

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

答案 1 :(得分:1)

您的代码存在多个问题。

printRecords有问题:

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

这是一个更正版本,它返回写入的记录数,如果无法打开文件,则返回-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指针,无论如何在文件中都是无用的。此文件只能在同一平台上回读,并使用相同的程序进行回写,这使得它成为备份或持久存储的不良选择。

答案 2 :(得分:0)

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

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