为什么我以2进制形式写入,然后用2进制读出来就是乱码了?

为什么我以2进制形式写入,然后用2进制读出来就是乱码了?

完整代码:
Library.h:

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#define MAX 50
#include<stdio.h>
#include<stdlib.h>
#include<String.h>
#include<time.h>

typedef struct//定义书结构体
{
    char name[MAX];//书名
    char number[MAX];//书的编号
    double price;//书的价格
    int num;//书的数量
}Book;

typedef struct//定义学生账号结构体
{
    int account;//账号
    char password[MAX];//密码
    char name[MAX];//姓名
    char student_number[MAX];//学号
    int num;//借书数量
    Book book[10];//借的书,并且最多只能借10本
}Student;

typedef struct Node//定义书链表
{
    Book data;
    struct Node* next;
}LinkList_book;

typedef struct Node1//定义学生账户链表
{
    Student data;
    struct Node1* next;
}LinkList_student;


//全局变量
//LinkList_book* L_book;//书链表
//LinkList_student* L_student;//学生账户链表

void CreateList_book();
void CreateList_student();

void welcome();

void Librarian();

void User();

void insert_book(char name[], char book_number[], double price, int num);
void insert_student(char password[], char name[], char student_number[],int &account);

LinkList_student* Find_student(int account); 
LinkList_book* Find_book(char name[]);

void DispBook(LinkList_book* book);//单本
void Disp_Book();//所有


void Delete_book(char name[]);
void Delete_student(char name[]);

void Sort_book();

void saveInfoToFile_book(const char* FileName);
void saveInfoToFile_student(const char* FileName);
void readInfoToFile_book(const char* FileName); 
void readInfoToFile_student(const char* FileName);

Library.cpp:

#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;

void welcome()
{
    printf("------  图书管理系统  -----------\n");
    printf("******  1.管理员身份   **********\n");
    printf("******  2.用户身份     **********\n");
    printf("******  0.退出程序     **********\n");
    printf("---------------------------------\n");
}

//创建链表
void CreateList_book()
{
    L_book = (LinkList_book*)malloc(sizeof(LinkList_book));
    L_book->next = NULL;
}
void CreateList_student()
{
    L_student = (LinkList_student*)malloc(sizeof(LinkList_student));
    L_student->next = NULL;
}

//链表的插入
void insert_book(char name[], char book_number[], double price, int num)
{
    LinkList_book* p = NULL;
    p = (LinkList_book*)malloc(sizeof(LinkList_book));
    //Book book = { name, book_number, price, num};//?
    Book book;
    strcpy(book.name, name);
    strcpy(book.number, book_number);
    book.price = price;
    book.num = num;
    p->data = book;
    LinkList_book* q = NULL;
    q = L_book;
    while (q->next != NULL)
    {
        q = q->next;
    }
    p->next = q->next;
    q->next = p;
}

void insert_student( char password[], char name[], char student_number[],int &account)
{
    LinkList_student* p = NULL;
    p = (LinkList_student*)malloc(sizeof(LinkList_student));
    //account = rand();//随机分配一个账户
    while(1)
    {
        account = rand(); 
        if (Find_student(account) == NULL)
        {
            break;
        }
    }
    //Student student = { temp_account, password, name, student_number, 0 };//?
    Student student;
    student.account = account;
    strcpy(student.password, password);
    strcpy(student.name, name);
    strcpy(student.student_number, student_number);
    student.num = 0;
    p->data = student;
    LinkList_student* q = NULL;
    q = L_student;
    while (q->next != NULL)
    {
        q = q->next;
    }
    p->next = q->next;
    q->next = p;
}

//根据账号查找
LinkList_student* Find_student(int account)
{
    LinkList_student* p = NULL;
    p = L_student->next;
    while (p != NULL)
    {
        if (p->data.account == account)
        {
            break;
        }
        p = p->next;
    }
    return p;
}
//根据图书名字查找
LinkList_book* Find_book(char name[])
{
    LinkList_book* p = NULL;
    p = L_book->next;
    while (p != NULL)
    {
        if (!strcmp(p->data.name, name))
        {
            break;
        }
        p = p->next;
    }
    return p;
}

//打印单本书
void DispBook(LinkList_book* book)
{
    printf("书名\t编号\t价格\t数量\n");
    printf("%s\t%s\t%f\t%d\n", book->data.name, book->data.number, book->data.price, book->data.num);
}

//打印所有图书
void Disp_Book()
{
    LinkList_book* temp_book = L_book->next;
    while (temp_book != NULL)
    {
        DispBook(temp_book);
        temp_book = temp_book->next;
    }
}

//删除书
void Delete_book(char name[])

{
    LinkList_book* p = NULL, *q = NULL;
    p = L_book;
    q = p->next;
    while (q != NULL)
    {
        if (strcmp(q->data.name, name) == 0)
        {
            p->next = q->next;
            free(q);
            break;
        }
        p = p->next;
        q = p->next;
    }
}

//删除学生账号
void Delete_student(char name[])
{
    LinkList_student* p = NULL, * q;
    q = p = L_student->next;
    while (p != NULL)
    {
        if (!strcmp(p->data.name, name))
        {
            q = q->next;
            break;
        }
        p = p->next;
        q = q->next;
    }
    p->next = q->next;
    free(q);
}

//按照价格图书排序
void Sort_book()
{
    LinkList_book* temp_book = L_book;//复制单链表
    LinkList_book* p = NULL, * q = NULL, *r = NULL;//使用两个指针
    r = temp_book;
    while (p != NULL && q != NULL)
    {
        p = r->next;
        q = p->next;
        if (p->data.price > q->data.price)
        {
            p->next = q->next;
            q->next = p;
            r->next = q;
        }
        r = p;
        DispBook(r);
    }
}

//文件写操作
void saveInfoToFile_book(const char* FileName)//书
{
    FILE* pf = fopen(FileName, "w");
    LinkList_book* pMove = L_book;
    while (pMove != NULL)
    {
        fwrite(&pMove, sizeof(Book), 1, pf);
        pMove = pMove->next;
    }
    fclose(pf);
    pf = NULL;
}

void saveInfoToFile_student(const char* FileName)
{
    FILE* pf = fopen(FileName, "w");
    LinkList_student* pMove = L_student;
    while (pMove != NULL)
    {
        fwrite(&pMove, sizeof(Student), 1, pf);
        pMove = pMove->next;
    }
    fclose(pf);
    pf = NULL;
}
//文件读操作
void readInfoToFile_book(const char* FileName)
{
    FILE* pf = fopen(FileName, "r");
    if (pf == NULL)
    {
        pf = fopen(FileName, "w+");
    }
    LinkList_book* pMove = NULL;
    while (fread(&pMove, sizeof(Book), 1, pf) != 0)
    {
        pMove = (LinkList_book*)malloc(sizeof(LinkList_book));
        insert_book(pMove->data.name, pMove->data.number, pMove->data.price, pMove->data.num);
    }
}

void readInfoToFile_student(const char* FileName)
{
    FILE* pf = fopen(FileName, "r");
    if (pf == NULL)
    {
        pf = fopen(FileName, "w+");
    }
    LinkList_student* pMove = NULL;
    while (fread(&pMove, sizeof(Book), 1, pf) != 0)
    {
        pMove = (LinkList_student*)malloc(sizeof(LinkList_student));
        insert_student(pMove->data.password, pMove->data.name, pMove->data.student_number, pMove->data.account);
    }
}

UserList.cpp:

#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;
void UserMenu()//用户菜单
{
    printf("------     用户界面    ----------\n");
    printf("******  1.登录         **********\n");
    printf("******  2.注册            *******\n");
    printf("******  0.返回上一层   **********\n");
    printf("---------------------------------\n");
}

void UserMenu2()
{
    printf("------     用户使用界面 ---------\n");
    printf("******  1.查找图书     **********\n");
    printf("******  2.查看已存图书    *******\n");
    printf("******  3.借阅图书        *******\n");
    printf("******  4.归还图书        *******\n");
    printf("******  5.按照价格图书排序*******\n");
    printf("******  0.返回上一层   **********\n");
    printf("---------------------------------\n");
}

void Register(LinkList_student* student)
{
    int input;
    char temp_name[MAX];
    LinkList_book* temp_book;
    do
    {
        UserMenu2();
        printf("请输入0-5:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            printf("--------【查找图书】---------\n");
            printf("请输入需要查找的图书名:>");
            scanf("%s", temp_name);
            temp_book = Find_book(temp_name);
            if (temp_book != NULL)
            {
                DispBook(temp_book);
            }
            else
            {
                printf("没有找到该图书\n");
            }
            break;
        case 2:
            printf("--------【查看已存图书】---------\n");
            Disp_Book();
            break;
        case 3:
            printf("--------【借阅图书】---------\n");
            printf("请输入要借阅图书的名字:>");
            scanf("%s", temp_name);
            temp_book = Find_book( temp_name);
            if (temp_book != NULL)
            {
                student->data.book[student->data.num++] = temp_book->data;//学生借的书本数量+1
                temp_book->data.num--;//图书馆里书本数量少1
            }
            else
            {
                printf("该图书尚且还未注册\n");
            }
            saveInfoToFile_book("book.txt");
            break;
        case 4:
            printf("--------【归还图书】---------\n");
            printf("请输入要归还图书的名字:>");
            scanf("%s", temp_name);
            temp_book = Find_book(temp_name);
            if (temp_book != NULL)
            {
                student->data.num--;
                Delete_book(temp_name);
            }
            else
            {
                printf("您还未借过该本书\n");
            }
            saveInfoToFile_book("book.txt");
            break;
        case 5:
            printf("--------【按照价格图书排序】---------\n");
            Sort_book();
            break;
        case 0:
            printf("-----------返回上一层------------\n");
            input = 0;
            break;
        default:
            printf("输入有误,请输入0-5间的数字\n");
            break;
        }
    } while (input);
}

void User()
{
    int input;
    int account;
    do
    {
        UserMenu();
        printf("请输入0-2:>");
        scanf("%d", &input);
        switch (input)
        {
            {
        case 1://登录
            LinkList_student * temp = NULL;//
            int account;//储存用户的账号
            char password[MAX];//储存用户的密码
            printf("--------【登录界面】---------\n");
            printf("请输入账号和密码:\n");
            printf("账号:>");
            scanf("%d", &account);
            temp = Find_student(account);
            if (temp == NULL)//未找到该账户
            {
                char ret = 0;
                printf("该用户不存在,是否注册,不注册则返回上一层:y/n:>");
                scanf(" %c", &ret);/////////////////////////////////////////
                if (ret == 'n')
                {
                    break;
                }
                printf("\n");
            }
            else//找到了
            {
                while (1)
                {
                    printf("密码:>");
                    scanf("%s", password);
                    if (!strcmp(password, temp->data.password))
                    {
                        printf("============登录成功==============\n");
                        Register(temp);
                        break;
                    }
                    else
                    {
                        printf("\n密码错误,请重新输入:>\n");
                    }
                }
                break;
            }
            }
        case 2:
            printf("--------【注册界面】---------\n");
            char temp_password[MAX];
            printf("请设置密码:>");
            scanf("%s", temp_password);
            char temp_name[MAX];
            printf("\n请输入姓名:>");
            scanf("%s", temp_name);
            char temp_student_number[MAX];
            printf("\n请输入学号:>");
            scanf("%s", temp_student_number);
            insert_student(temp_password, temp_name, temp_student_number, account);
            printf("\n注册成功,你的账号为:%d\n", account);
            saveInfoToFile_student("student.txt");
            break;
        case 0:
            printf("-----------返回上一层------------\n");
            input = 0;
            break;
        default:
            printf("输入有误,请输入0-2间的数字\n");
            break;
        }
    } while (input);
}

Libralian.cpp

#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;
void LibrarianMenu()//管理员菜单
{
    printf("-------    管理员界面   ---------\n");
    printf("******  1.注册新图书   **********\n");
    printf("******  2.查看已存图书    *******\n");
    printf("******  3.修改已有图书    *******\n");
    printf("******  4.注销现存图书    *******\n");
    printf("******  0.返回上一层    *********\n");
    printf("---------------------------------\n");
}

void Librarian()
{
    int input = 0;
    do
    {
        LibrarianMenu();
        printf("请输出0-4:>");
        scanf("%d", &input);
        LinkList_book* temp_book = NULL;//临时书本
        char temp_name[MAX];//临时书本名
        char temp_number[MAX];//临时书本编号
        double temp_price;//临时书本价格
        int temp_num;//临时书本数量
        int temp;//临时选项
        switch (input)
        {
        case 1:
            printf("--------【注册新图书】---------\n");
            printf("书名:>");
            scanf("%s", temp_name);
            printf("\n编号:>");
            scanf("%s", temp_number);
            printf("\n价格:>");
            scanf("%lf", &temp_price);
            printf("\n数量:>");
            scanf("%d", &temp_num);
            printf("\n");
            insert_book(temp_name, temp_number, temp_price, temp_num);
            saveInfoToFile_book("book.txt");
            break;
        case 2:
            printf("--------【查看已存图书】---------\n");
            Disp_Book();
            break;
        case 3:
            printf("--------【修改已有图书】---------\n");
            printf("请输入需要修改书本的名字:>");
            scanf("%s", temp_name);
            printf("\n");
            temp_book = Find_book(temp_name);
            if (temp_book == NULL)
            {
                printf("该图书尚未注册\n");
            }
            else
            {
                printf("-----------------------\n");
                printf("********1.书名*********\n");
                printf("********2.编号*********\n");
                printf("********3.价格*********\n");
                printf("********4.数量*********\n");
                printf("请选择需要修改的选项:>");
                scanf("%d", &temp);
                switch (temp)
                {
                case 1:
                    printf("修改后的书名:>");
                    scanf("%s", temp_name);
                    strcpy(temp_book->data.name, temp_name);
                    break;
                case 2:
                    printf("修改后的编号:>");
                    scanf("%s", temp_number);
                    strcpy(temp_book->data.number, temp_number);
                    break;
                case 3:
                    printf("修改后的价格:>");
                    scanf("%lf", &temp_price);
                    temp_book->data.price = temp_price;
                    break;
                case 4:
                    printf("修改后的数量:>");
                    scanf("%lf", &temp_num);
                    temp_book->data.num = temp_num;
                    break;
                }
            }
            saveInfoToFile_book("book.txt");
            break;
        case 4:
            printf("--------【注销现存图书】---------\n");
            printf("请输入要删除的书名:>");
            scanf("%s", temp_name);
            Delete_book(temp_name);
            printf("-----删除成功%s-----\n", temp_name);
            saveInfoToFile_book("book.txt");
            break;
        case 0:
            printf("-----------返回上一层------------\n");
            input = 0;
            break;
        default:
            printf("输入有误,请输入0-4间的数字\n");
            break;
        }
    } while (input);
}

test.cpp:

#include"Library.h"
LinkList_book* L_book;
LinkList_student* L_student;
int main()
{
    CreateList_book();
    CreateList_student();
    readInfoToFile_book("book.txt");
    readInfoToFile_student("student.txt"); 
    srand((unsigned int)time(NULL));
    int input = 0;// 控制用户的输入的变量
    do
    {
        welcome();//进入菜单
        printf("请选择0-2:>");
        scanf("%d", &input);//用户选择
        switch(input)
        {
        case 1://选择管理员
            Librarian();//进入管理员界面
            break;
        case 2://选择用户
            User();//进入用户界面
            break;
        case 0:
            printf("退出程序\n");
            break;
        default:
            printf("输入有误,请输入0-2间的数字\n");
            break;
        }
        //system("cls");
    } while (input);//输入为0自动退出
    return 0;
}

Library.cpp: 修改如下,改动处见注释,供参考:

#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;

void welcome()
{
    printf("------  图书管理系统  -----------\n");
    printf("******  1.管理员身份   **********\n");
    printf("******  2.用户身份     **********\n");
    printf("******  0.退出程序     **********\n");
    printf("---------------------------------\n");
}

//创建链表
void CreateList_book()
{
    L_book = (LinkList_book*)malloc(sizeof(LinkList_book));
    L_book->next = NULL;
}
void CreateList_student()
{
    L_student = (LinkList_student*)malloc(sizeof(LinkList_student));
    L_student->next = NULL;
}

//链表的插入
void insert_book(char name[], char book_number[], double price, int num)
{
    LinkList_book* p = NULL;
    p = (LinkList_book*)malloc(sizeof(LinkList_book));
    p->next = NULL;
                      //Book book = { name, book_number, price, num};//  修改
                      //Book book;
    strcpy(p->data.name,name);         //strcpy(book.name, name);
    strcpy(p->data.number,book_number); //strcpy(book.number, book_number);
    p->data.price = price;              //book.price = price;
    p->data.num = num;                  //book.num = num;
                                        //p->data = book;
    LinkList_book* q = NULL;
    q = L_book;
    while (q->next != NULL)
    {
        q = q->next;
    }
    p->next = q->next;
    q->next = p;
}

//根据账号查找
LinkList_student* Find_student(int account)
{
    LinkList_student* p = NULL;
    p = L_student->next;
    while (p != NULL)
    {
        if (p->data.account == account)
        {
            break;
        }
        p = p->next;
    }
    return p;
}

void insert_student( char password[], char name[], char student_number[],int &account)
{
    LinkList_student* p = NULL;
    p = (LinkList_student*)malloc(sizeof(LinkList_student));
    p->next = NULL;
   
    while(1) //account = rand();//随机分配一个账户
    {
        account = rand();
        if (Find_student(account) == NULL)
        {
            break;
        }
    }
    //Student student = { temp_account, password, name, student_number, 0 };// 修改
    //Student student;
    p->data.account = account;         //student.account = account;
    strcpy(p->data.password, password); //strcpy(student.password, password);
    strcpy(p->data.name, name);       //strcpy(student.name, name);
    strcpy(p->data.student_number, student_number);//strcpy(student.student_number, student_number);
    p->data.num = 0;                 //student.num = 0;
                                     //p->data = student;
    LinkList_student* q = NULL;
    q = L_student;
    while (q->next != NULL)
    {
        q = q->next;
    }
    p->next = q->next;
    q->next = p;
}


//根据图书名字查找
LinkList_book* Find_book(char name[])
{
    LinkList_book* p = NULL;
    p = L_book->next;
    while (p != NULL)
    {
        if (!strcmp(p->data.name, name))
        {
            break;
        }
        p = p->next;
    }
    return p;
}

//打印单本书
void DispBook(LinkList_book* book)
{
    printf("书名\t编号\t价格\t数量\n");
    printf("%s\t%s\t%f\t%d\n", book->data.name, book->data.number, book->data.price, book->data.num);
}

//打印所有图书
void Disp_Book()
{
    LinkList_book* temp_book = L_book->next;
    while (temp_book != NULL)
    {
        DispBook(temp_book);
        temp_book = temp_book->next;
    }
}

//删除书
void Delete_book(char name[])

{
    LinkList_book* p = NULL, *q = NULL;
    p = L_book;
    q = p->next;
    while (q != NULL)
    {
        if (strcmp(q->data.name, name) == 0)
        {
            p->next = q->next;
            free(q);
            break;
        }
        p = p->next;
        q = p->next;
    }
}

//删除学生账号
void Delete_student(char name[])
{
    LinkList_student* p = NULL, * q;
    q = p = L_student->next;
    while (p != NULL)
    {
        if (!strcmp(p->data.name, name))
        {
            q = q->next;
            break;
        }
        p = p->next;
        q = q->next;
    }
    p->next = q->next;
    free(q);
}

//按照价格图书排序
void Sort_book()
{
    LinkList_book* temp_book = L_book;//复制单链表
    LinkList_book* p = NULL, * q = NULL, *r = NULL;//使用两个指针
    r = temp_book;
    while (p != NULL && q != NULL)
    {
        p = r->next;
        q = p->next;
        if (p->data.price > q->data.price)
        {
            p->next = q->next;
            q->next = p;
            r->next = q;
        }
        r = p;
        DispBook(r);
    }
}

//文件写操作
void saveInfoToFile_book(const char* FileName)//书
{
    FILE* pf = fopen(FileName, "w");
    LinkList_book* pMove = L_book;
    while (pMove != NULL)
    {
        fwrite(&pMove->data, sizeof(Book), 1, pf); //修改
        //fwrite(&pMove, sizeof(Book), 1, pf);
        pMove = pMove->next;
    }
    fclose(pf);
    pf = NULL;
}

void saveInfoToFile_student(const char* FileName)
{
    FILE* pf = fopen(FileName, "w");
    LinkList_student* pMove = L_student;
    while (pMove != NULL)
    {
        fwrite(&pMove->data, sizeof(Student), 1, pf);  // 修改
        // fwrite(&pMove, sizeof(Student), 1, pf);
        pMove = pMove->next;
    }
    fclose(pf);
    pf = NULL;
}
//文件读操作
void readInfoToFile_book(const char* FileName)
{
    FILE* pf = fopen(FileName, "r");
    if (pf == NULL)
    {
        pf = fopen(FileName, "w+");
    }
    //LinkList_book* pMove = NULL;
    Book book;  // 修改
    while (1)   // 修改
    {
        if (fread(&book, sizeof(Book), 1, pf) != 1) break; // 修改
        insert_book(book.name, book.number, book.price, book.num); // 修改
    }
    fclose(pf);
}

void readInfoToFile_student(const char* FileName)
{
    FILE* pf = fopen(FileName, "r");
    if (pf == NULL)
    {
        pf = fopen(FileName, "w+");
    }
    //LinkList_student* pMove = NULL;
    Student stu;  // 修改
    while (1)     // 修改
    {
        if (fread(&stu, sizeof(Student), 1, pf) != 1) break; //sizeof(Book) 修改
        insert_student(stu.password, stu.name, stu.student_number, stu.account); // 修改
    }
    fclose(pf);
}

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    答案:

    在使用写入二进制文件时,我们需要注意以下两点:

    1. 写入时需要考虑写入的数据类型和数据长度,将数据以固定的大小写入文件中,读取的时候需要按照固定的大小读取。

    2. 在读取时需要考虑读取的数据类型和数据长度是否与写入时一致,否则将可能读取到错误的数据,导致乱码的情况出现。

    根据以上两点,我们可以修改代码为:

    // 写入二进制文件
    std::ofstream out("myfile.bin", std::ios::binary);
    int a = 123;
    out.write(reinterpret_cast<char*>(&a), sizeof(int));
    out.close();
    
    // 读取二进制文件
    std::ifstream in("myfile.bin", std::ios::binary);
    int b;
    in.read(reinterpret_cast<char*>(&b), sizeof(int));
    in.close();
    std::cout << b << std::endl;
    

    在写入和读取时,我们使用了reinterpret_cast显式转换指针类型,将指针类型从int转变成char类型,这是为了保证写入和读取的数据长度一致,从而避免出现乱码的情况。

    如果还存在乱码的问题,可以尝试使用Windows下提供的二进制编辑器HexEdit查看二进制文件的内容,以确定问题出现的位置。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^