从文件c ++中读取数据库

时间:2013-05-19 22:17:44

标签: c++ database class io

我正在尝试从文件中读取数据库。

这是我的save_base方法:

void data_base::save_base()
{
    fstream file;

    file.open("base.dat", ios::in | ios::out | ios::trunc);

    if(file.good()==true) {
        node *p = new node();
        p=first;

        while(p) {
            file << p->content->connect() << ";" << "\n";
            p=p->next;
        }
        file.close();
    }else{
    cout << "Err - opening file." << endl;
    }
}

连接方法:

string product::connect() {

    ostringstream do_string;
    do_string << lp;
    string new_lp = do_string.str();

    ostringstream do_string1;
    do_string1 << count;
    string new_count = do_string1.str();

    ostringstream do_string2;
    do_string2 << prize;
    string new_prize = do_string2.str();

    ostringstream do_string3;
    do_string3 << vat;
    string new_vat = do_string3.str();

    string connected = type + ";" + new_lp + ";" + name + ";" + new_count + ";" + unit + ";" + new_prize + ";" + new_vat;
    return connected;
}

和read_base方法:

void data_base::read_base()
{
    fstream file;

    file.open("base.dat", ios::in);
    if(file.good()==true)
    {
        char data_row[50];
        int i=1;
        while(!file.eof()) {
            file.getline(data_row,100);

        string data_content[50];
        int j = 0;

        char *buff;
        buff = strtok (data_row,";");
        while (buff != NULL)    {
            data_content[j] = buff;
            buff = strtok (NULL, ";");
            j++;
        }
        string type = data_content[0];
        int lp;
        istringstream iss1(data_content[1]);
        iss1 >> lp;
        double count;
        istringstream iss2(data_content[3]);
        iss2 >> count;
        double prize;
        istringstream iss3(data_content[5]);
        iss3 >> prize;
        double vat;
        istringstream iss4(data_content[5]);
        iss4 >> vat;

        // Sprawdzamy typ obiektu zapisanego w danym wierszu pliku
        if(type == "product")
        {

            product new_prod(lp, data_content[2], count, data_content[4], prize, vat);
            product *new_product = new product(new_prod);
            this->add(new_product);
        }
        i++;
        }
    file.close();
    }else{
        cout << "Err opening file." << endl;
    }
}

我正在向数据库添加一些产品,它运行正常。即使保存到文件也很有效。但主要问题是当我试图从文件中读取数据库时。从文件中读取数据库工作正常,但最后,应用程序不会自行结束。我认为还有一些缓冲要关闭。但我不知道他们是哪个或多近。

2 个答案:

答案 0 :(得分:1)

老实说 - 你在这段代码中遇到了很多问题,我建议你的主要问题是你可能仍在努力解决封装问题。您的代码使用了C和C ++样式的混合,这些样式保证使代码难以阅读并因此维护,这就是为什么您在这里并且人们正在努力为您提供答案。

那说,问题看起来就是在保存你正在调用“新节点()”,看起来你要保存......什么都没有。你不应该质疑产品中的一些现有价值吗?编辑:啊 - 不,你现在重新分配它是“p =第一”,我明白了。那么你在前一行分配的节点会发生什么?

当你的任何行超过50个字节时,你也有一个潜在的堆栈崩溃:

char data_row[50];
int i=1;
while(!file.eof()) {
    file.getline(data_row,100);

如果你必须使用char数组,请进入使用sizeof:

的习惯
file.getline(data_row, sizeof(data_row));

我花了一些时间来弄清楚istringstreams的用途 - 您是否正在尝试将字符串转换为数字?写得更简单,更有效率:

unsigned int lp = atoi(data_content[1].c_str());
or
unsigned int lp = strtoul(data_content[1].c_str(), NULL, 10);

您的read_base函数是数据库的一部分,它非常了解WAAAAY数据记录。您需要封装记录填充,以便read_base看起来更像:

void data_base::read_base()
{
    fstream file("base.dat", ios::in);
    if(file.good() == false) {
        cout << "Error opening file." << endl;
        return;
    }

    for(size_t rowNo = 0; !file.eof(); ++rowNo) {
        row* row = data_type::make_object_from_row(file);
        if(row != nullptr)
            this->add(row);
        }
    }
}

您可能需要查看“工厂模式”,了解如何实现可以执行此操作的data_row基类型。但简而言之,您使产品继承data_type,以便上述工作。 data_type :: make_object_from_row将读取行的第一部分并枚举类型,以便它可以执行以下操作:

data_type* data_type::make_object_row_row(istream& file) {
    switch(get_type(file)) {
        case DATA_TYPE_PRODUCT: return new product(file);
        case DATA_TYPE_PERSON: return new person(file);
        default:
          clog << "invalid type in database: " << type << endl;
          return nullptr;
    }
}

(这只是一种可能的方法)。

答案 1 :(得分:0)

我发现至少有一个可能产生未定义行为的明显错误。您正在分配50个字节,但最多可读取100个字节。

    char data_row[50];
    int i=1;
    while(!file.eof()) {
        file.getline(data_row,100);

我建议在此代码中将50更改为100。