在c++中读写.dat文件

问题描述 投票:0回答:1

我目前正在学习c++编程。我正在通过我在网上找到的一个编程项目,并尝试逐行重新创建它,寻找为什么某些事情的工作方式。这个项目是一个简单的酒店预订系统,它有一个菜单系统,并保存用户的输入,如姓名,地址,电话号码等。

我一直在寻找关于试图了解这段代码的某些部分。我想把用户的输入和保存到一个.dat文件,但它似乎并没有工作,我不知道为什么。有没有更好的方法来读写文本文件。

这是处理检查房间是否空闲或保留的函数。

#include <fstream>
#include "Hotel.h"

int Hotel::check_availabilty(int room_type){

    int flag = 0;
    std::ifstream room_check("Room_Bookings.dat",std::ios::in);

    while(!room_check.eof()){

        room_check.read((char*)this, sizeof(Hotel));

        //if room is already taken
        if(room_no == room_type){

            flag = 1;
            break;

        }
    }
    room_check.close();//close the ifstream
    return(flag);//return result
}

这是预订房间的代码

#include "Hotel.h"
#include "check_availability.cpp"

void Hotel::book_a_room()
{

    system("CLS");//this clears the screen

    int flag;
    int room_type;


    std::ofstream room_Booking("Room_Bookings.dat");

    std::cout << "\t\t" << "***********************" << "\n";
    std::cout << "\t\t  " << "THE GREATEST HOTEL" << "\n";
    std::cout << "\t\t" << "***********************" << "\n";
    std::cout << "\t\t " <<"Type of Rooms "<< "\t\t Room Number" "\n";
    std::cout << "\t\t" << " Standard" << "\t\t   1 - 30" "\n";
    std::cout << "\t\t" << " Luxury" << "\t\t\t  31 - 45" "\n";
    std::cout << "\t\t" << " Royal" << "\t\t\t  46 - 50" "\n";

    std::cout << "Please enter room number: ";
    std::cin >> room_type;

    flag = check_availabilty(room_type);

    if(flag){
        std::cout << "\n Sorry, that room isn't available";
    }
    else{

        room_no = room_type;
        std::cout<<" Name: ";
        std::cin>>name;
        std::cout<<" Address: ";
        std::cin>>address;
        std::cout<<" Phone No: ";
        std::cin>>phone;

        room_Booking.write((char*)this,sizeof(Hotel));
        std::cout << "Your room is booked!\n";

    }
    std::cout << "Press any key to continue...";
    getch();
    room_Booking.close();


}

这是Hotel.h文件

class Hotel
{
    int room_no;
    char name[30];
    char address[50];
    char phone[10];

    public:
        void main_menu();
        void book_a_room();
        int check_availabilty(int);
        void display_details();
};

我不完全理解这部分while循环的作用。

room_check.read((char*)this, sizeof(Hotel));

如果你需要更多的信息,请问.任何提示和技巧,使这个更好的将受到欢迎。

c++ ifstream ofstream
1个回答
4
投票

Hotel 是一个完全自足的类型,没有堆分配或对外部对象的引用。 因此,我们可以通过简单地写出对象在内存中的表示来序列化它的状态,并通过做相反的事情来反序列化。

room_check.read((char*)this, sizeof(Hotel));

这行代码要求 room_check 输入流读取 sizeof(Hotel) 字节,并将其直接存储在 Hotel 所指向的对象 this 的生命。 实际上,你是将内存内容恢复到写入磁盘之前的状态。

(注意 (char*)this 最好写成 reinterpret_cast<char *>(this) 在C++中。)

这就是这个操作的反面。

room_Booking.write((char*)this,sizeof(Hotel));

用这种方式序列化而不是创建自己的数据结构有一些优势.

  • 它真的很简单,用一行代码就可以序列化,用另一行代码就可以反序列化。
  • 序列化和反序列化的速度非常快,因为没有发生解析或转换。

但是,也有一些缺点。

  • 磁盘上的格式是由内存中对象的布局决定的。如果你重新排序或改变任何类的数据成员,旧的序列化对象将无法再正确加载。 此外,读取操作会成功,但你会留下一个垃圾对象状态。
  • 对于数字类型,你依赖于主机的endianness。一个在小恩迪安机器上创建的数据文件在大恩迪安机器上将毫无用处。
  • 很容易不小心造成安全漏洞。例如,只用这段代码,攻击者就可以很容易地制作一个 .dat 文件,当你去读取 "字符串"(字符数组)成员时,只要不对这些数组中的任何一个数组进行NUL终结,就会导致越界读取。

使用不同的序列化机制,如利用JSON、XML、协议缓冲区等,需要更多的工作,但结果更可移植,因为你在磁盘上的数据结构不再与对象在内存中的布局挂钩。


1
投票

当进行

room_check.read((char*)this, sizeof(Hotel));

你从流中读取数据,并写入缓冲区,但你需要指定必须读取多少字符...


1
投票

room_check 包含的数据是一个流。room_check.read((char*)this, sizeof(Hotel)); 从流中读取数据,并将其存储在当前实例的 Hotel (this). sizeof(Hotel) 告诉函数应该从流中读取多少字节。

room_check 包含类的数据 Hotel 在类声明中按顺序排列。

int room_no;
char name[30];
char address[50];
char phone[10];

有了这个声明,一个酒店实例的字节大小是已知的。sizeof(1*int + 30*char + 50*char + 10*char). 数据文件的内容被存储在当前的这个 Hotel.

© www.soinside.com 2019 - 2024. All rights reserved.