从二进制文件读取结构数据时获取垃圾值

时间:2013-10-23 02:37:44

标签: c++ data-structures struct inputstream garbage

大家好,在上一个问题中,我能够获取要加载到文件中的结构数据,但现在问题是我在检索它时会获得垃圾值。

文件内容:settings.bin

110#NormalCompression Level210#NormalCompression Level310#NormalCompression Level410#NormalCompression Level510#NormalCompression Level

代码

#include<cstdlib>
#include<iostream>
#include<string>
#include<iomanip>
#include<fstream.h>

using namespace std;

const char* ErrorLogFilePath = "resources\\error.txt";
const char* SettingsFilePath = "resources\\settings.bin";
const int NoOfSettings = 5;

struct Setting {
    int SettingID;
    int SettingINTValue;
    double SettingDOUBLEValue;
    char SettingCHARValue;
    string SettingSTRINGValue;
    string SettingName;
};

istream& operator>>(istream& _is, Setting& _s) {
    _is>>_s.SettingID;
    _is>>_s.SettingINTValue;
    _is>>_s.SettingDOUBLEValue;
    _is>>_s.SettingCHARValue;
    _is>>_s.SettingSTRINGValue;
    _is>>_s.SettingName;
}

ostream& operator<<(ostream& _os, const Setting& _s) {
    _os<<_s.SettingID;
    _os<<_s.SettingINTValue;
    _os<<_s.SettingDOUBLEValue;
    _os<<_s.SettingCHARValue;
    _os<<_s.SettingSTRINGValue;
    _os<<_s.SettingName;
}

class ErrorReport {
public:
    fstream ErrorFile;
    void PostError(string Title,string Data,int ErrorID) {
        ErrorFile.open(ErrorLogFilePath,ios::out);
        ErrorFile.close();
    }
} Error;

class SettingsClass {
public:
    Setting setting[NoOfSettings];
    void ResetSettings() {
        fstream SettingFile;
        Setting defaultsetting[NoOfSettings];

        for(int i=1; i<=NoOfSettings; i++) {
            defaultsetting[i-1].SettingID = i;
            defaultsetting[i-1].SettingINTValue = 0;
            defaultsetting[i-1].SettingDOUBLEValue = 0;
            defaultsetting[i-1].SettingCHARValue = '#';
            defaultsetting[i-1].SettingSTRINGValue = "null";
            switch(i) {
            default:
                defaultsetting[i-1].SettingName = "Compression Level";
                defaultsetting[i-1].SettingSTRINGValue = "Normal";
                defaultsetting[i-1].SettingINTValue = 1;
                break;
            }
        }

        SettingFile.open(SettingsFilePath,ios::binary|ios::out);
        if(SettingFile.is_open()) {
            for(size_t i=0; i<NoOfSettings; ++i) {
                SettingFile<<defaultsetting[i];
            }
        } else {
            cout<<"Error!";
        }
        SettingFile.close();

    }
    void _SettingsClass() {
        fstream SettingFile;
        SettingFile.open(SettingsFilePath,ios::binary|ios::in);
        Setting TempSettings[NoOfSettings];
        if(SettingFile.is_open()) {
            for(size_t i=0; i<NoOfSettings; ++i) {
                SettingFile>>TempSettings[i];
            }
        } else {
            cout<<"Error...";
        }
        SettingFile.close();
        for(int i=0; i<NoOfSettings; i++) {
            cout<<TempSettings[i].SettingINTValue<<"\n";
        }
    }
} Settings;

int main(int argc, char *argv[])
{
    Settings._SettingsClass();
//    cout<<Settings.GetSetting(1).SettingName;
    system("PAUSE");
    return EXIT_SUCCESS;
}

输出

4473076
1
3
0
2686384

现在为什么我得到那些垃圾值?任何人都可以帮助我,因为我认为它不应该像这样(?)。我应该为该struct数组的每个元素得到1。

提前致谢!

2 个答案:

答案 0 :(得分:2)

格式化输入需要分隔符,因此它知道何时停止读取特定值。即使您以二进制模式打开文件,您所编写的内容本质上也是一个没有分隔符的文本文件,因此您无法将其读回。

如果你必须有一个二进制文件,那么这是使用你的结构读/写的方法:

#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <vector>

const char* SettingsFilePath = "settings.bin";

struct Setting
{
    int SettingID;
    int SettingINTValue;
    double SettingDOUBLEValue;
    char SettingCHARValue;
    std::string SettingSTRINGValue;
    std::string SettingName;

    Setting()
        : SettingID(0)
        , SettingINTValue(0)
        , SettingDOUBLEValue(0)
        , SettingCHARValue(0)
    {
    }

    void Write(std::fstream& out)
    {
        out.write(reinterpret_cast<const char*>(&SettingID), sizeof(SettingID));

        out.write(reinterpret_cast<const char*>(&SettingINTValue), sizeof(SettingINTValue));

        out.write(reinterpret_cast<const char*>(&SettingDOUBLEValue), sizeof(SettingDOUBLEValue));

        out.write(reinterpret_cast<const char*>(&SettingCHARValue), sizeof(SettingCHARValue));

        size_t str_size = SettingSTRINGValue.size();
        out.write(reinterpret_cast<const char*>(&str_size), sizeof(str_size));
        out.write(SettingSTRINGValue.c_str(), SettingSTRINGValue.size());

        str_size = SettingName.size();
        out.write(reinterpret_cast<const char*>(&str_size), sizeof(str_size));
        out.write(SettingName.c_str(), SettingName.size());
    }

    void Read(std::fstream& in)
    {
        in.read(reinterpret_cast<char*>(&SettingID), sizeof(SettingID));

        in.read(reinterpret_cast<char*>(&SettingINTValue), sizeof(SettingINTValue));

        in.read(reinterpret_cast<char*>(&SettingDOUBLEValue), sizeof(SettingDOUBLEValue));

        in.read(reinterpret_cast<char*>(&SettingCHARValue), sizeof(SettingCHARValue));

        size_t str_size;
        std::vector<char> str_data;

        in.read(reinterpret_cast<char*>(&str_size), sizeof(str_size));
        str_data.resize(str_size);
        in.read(&str_data[0], str_size);
        SettingSTRINGValue.assign(str_data.begin(), str_data.end());

        in.read(reinterpret_cast<char*>(&str_size), sizeof(str_size));
        str_data.resize(str_size);
        in.read(&str_data[0], str_size);
        SettingName.assign(str_data.begin(), str_data.end());
    }

    void Print(const std::string& title)
    {
        std::cout << title << "\n";
        std::cout << std::string(title.size(), '-') << "\n";

        const size_t w = 22;
        std::cout << std::setw(w) << std::right << "SettingID : " << SettingID << "\n";
        std::cout << std::setw(w) << std::right << "SettingINTValue : " << SettingINTValue << "\n";
        std::cout << std::setw(w) << std::right << "SettingDOUBLEValue : " << SettingDOUBLEValue << "\n";
        std::cout << std::setw(w) << std::right << "SettingCHARValue : " << SettingCHARValue << "\n";
        std::cout << std::setw(w) << std::right << "SettingSTRINGValue : " << SettingSTRINGValue << "\n";
        std::cout << std::setw(w) << std::right << "SettingName : " << SettingName << "\n";

        std::cout << "\n";
    }
};

int main()
{
    {
        Setting s;
        s.Print("Default before Write");

        s.SettingID = 1;
        s.SettingINTValue = 2;
        s.SettingDOUBLEValue = 3.5;
        s.SettingCHARValue = 'Z';
        s.SettingSTRINGValue = "Blah Blah";
        s.SettingName = "Some Settings";

        std::fstream f(SettingsFilePath, std::ios::out | std::ios::binary);
        s.Write(f);

        s.Print("Values written to file");
    }

    {
        Setting s;
        s.Print("Default before read");

        std::fstream f(SettingsFilePath, std::ios::in | std::ios::binary);
        s.Read(f);
        s.Print("Values after read");
    }

    return EXIT_SUCCESS;
}

答案 1 :(得分:0)

您似乎忘了将设置加载到文件中。

int main(int argc, char *argv[])
{
    Settings.ResetSettings();  // insert code here
    Settings._SettingsClass();
    //    cout<<Settings.GetSetting(1).SettingName;
    system("PAUSE");
    return EXIT_SUCCESS;
}