0

Hi guys in my previous question, I was able to get the data of a struct to be loaded on a file, but now the issue is I'm getting garbage value while retrieving it.

File Contents: settings.bin

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

Code

#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;
}

Output

4473076
1
3
0
2686384

Now Why I'm getting those garbage values? Can anyone help me, cause I think it should not turn up like this(?). And I should be getting 1 for each such element of that struct array.

Thanks in Advance!

2 Answers 2

2

Formatted input requires delimiters so it knows when to stop reading for a particular value. Even though you're opening the file in binary mode what you're writing is in essence a text file with no delimiters so you can't read it back.

If you must have a binary file then this is the way to read/write one using your structure:

#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;
}
Sign up to request clarification or add additional context in comments.

Comments

0

It seems you forgot to load your setting into file.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.