Programmeinstellungen speichern (strukt,klasse, welche methoden/funktionen)



  • Hallo,
    also die letzten programme die ich geschrieben habe, hatten schon immer ein paar
    einstellmöglickeiten. Ich sag jetzt mal, dass ich so ca. 10 bis 20 variablen
    hatte die ich speichern musste. Das sind dann Strings, ints und bools etc... Es
    könnte halt alles sein. Wie würdet ihr sowas jetzt handhaben. Angenommen ihr
    habt ein FTP-Client geschrieben und möchtet die Daten der letzten Sitzung
    speichern. Mit Handhaben mein ich jetzt nicht nur die Speicherung auf dem
    Datenträger, sondern auch die speicherung im speicher.
    Also wenn man z.b. sowas hätte:

    //Ftp Server Daten
       AnsiString Username;
       AnsiString Password;
       AnsiString Ip;
       short      port
       bool       Ascii;
    
       //Programmeneinstellungen
       bool Vollbildmodus;
       bool AutoConnect;   
       bool AutoSave;
    

    Wie programmiert ihr das jetzt?



  • Also so könnte man das doch lösen, oder wäre euch das zu "aufwändig"?

    //struct zur übersichtlichkeit?
    struct TFtpServer
    {
       AnsiString Username;
       AnsiString Password;
       AnsiString Ip;
       short      port
       bool       Ascii;
    }
    
    // Klasse zum verwalten der optionen.
    class TOptionen
    {
       private:
       public:
    
          //Ftp Server Daten
          TFtpServer FtpServer;
    
          //Programmeneinstellungen
          bool Vollbildmodus;
          bool AutoConnect;
          bool AutoSave;
    
          /* Methoden */
          void SaveToIni();
          bool LoadFromIni();
    };
    
    bool TOptionen::LoadFromIni()
    {
       if( !FileExists( ChangeFileExt( Application->ExeName, ".INI") )
       {
          return false;
       }
       else
       {
          TIniFile *ini;
          ini = new TIniFile( ChangeFileExt( Application->ExeName, ".INI")  );
    
          //FtpServerDaten
          ini->ReadString(  "FtpServerDaten", "Username", "");
          ini->ReadString(  "FtpServerDaten", "Password", "");
          ini->ReadString(  "FtpServerDaten", "Ip",       "");
          ini->ReadInteger( "FtpServerDaten", "Port",     21);
          ini->ReadBool(    "FtpServerDaten", "Ascii",    true);
    
          //Programmeinstellungen
          ini->ReadBool( "Programmeinstellungen", "Vollbildmodus", true);
          ini->ReadBool( "Programmeinstellungen", "AutoConnect",   true);
          ini->ReadBool( "Programmeinstellungen", "AutoSave",      true);
    
          delete ini;
       }
    
       return true;
    }
    
    void TOptionen::SaveToIni()
    {
       TIniFile *ini;
       ini = new TIniFile( ChangeFileExt( Application->ExeName, ".INI")  );
    
       //FtpServerDaten
       ini->WriteString(  "FtpServerDaten", "Username", this->FtpServer.Username);
       ini->WriteString(  "FtpServerDaten", "Password", this->FtpServer.Password);
       ini->WriteString(  "FtpServerDaten", "Ip",       this->FtpServer.Ip;
       ini->WriteInteger( "FtpServerDaten", "Port",     this->FtpServer.port);
       ini->WriteBool(    "FtpServerDaten", "Ascii",    this->FtpServer.Ascii);
    
       //Programmeinstellungen
       ini->WriteBool( "Programmeinstellungen", "Vollbildmodus", this->Vollbildmodus);
       ini->WriteBool( "Programmeinstellungen", "AutoConnect",   this->AutoConnect);
       ini->WriteBool( "Programmeinstellungen", "AutoSave",      this->AutoSave);
    
       delete ini;
    }
    


  • Andere möglichkeit wäre noch diese hier:

    //struct zur übersichtlichkeit?
    struct TFtpServer
    {
       AnsiString Username;
       AnsiString Password;
       AnsiString Ip;
       short      port
       bool       Ascii;
    }
    
    // Klasse zum verwalten der optionen.
    class TOptionen
    {
       private:
       public:
    
          //Ftp Server Daten
          TFtpServer FtpServer;
    
          //Programmeneinstellungen
          bool Vollbildmodus;
          bool AutoConnect;
          bool AutoSave;
    
          /* Methoden */
          bool SaveToFile();
          bool LoadFromFile();
    };
    
    bool TOptionen::LoadFromFile()
    {
       if( !FileExists( ChangeFileExt( Application->ExeName, ".dat") )
       {
          return false;
       }
       else
       {
          fstream Datei;
          if( Datei.open( ChangeFileExt( Application->ExeName, ".dat"), ios::in | ios::binary ) )
          {
             Datei.read( (char*)this, ( sizeof(this) );
             Datei.close();
          }
          else
          {
             return false;
          }
       }
    
       return true;
    }
    
    bool TOptionen::SaveToFile()
    {
       fstream Datei;
       if( Datei.open( ChangeFileExt( Application->ExeName, ".dat"), ios::out | ios::binary ) )
       {
          Datei.write( (char*)this, ( sizeof(this) );
          Datei.close();
          return true;
       }
       else
       {
          return false;
       }
    }
    

    Allerdings bekomme ich hier den huddel, dass ich probleme mit den, in der
    größe dynamischen, attributen bekomme. Ich muss ja dann vorher noch die
    ansistrings in char arrays mit fixer länger schreiben, dort zwischen speichern
    und dann erst auf den datenträger schreiben.
    Ich weiß auch gerade gar nicht ob das mit dem

    Datei.write( char*)this, ( sizeof(this) );
    

    so einfach geht. Ich hab das sonst mit structs und nicht mit klassen gemacht.



  • Filestreams kommen für sowas auch nicht in Frage oder?

    Gibt es denn irgendwas, das mit den AnsiStrings so fertig wird, außer die ini files?



  • Hallo

    TFileStreams können schon mit AnsiStrings umgehen, die std::fstreams mit einem Trick auch.

    Aber was gefällt dir an TIniFile nicht? Das scheint genau das richtige für deinen Zweck zu sein.

    bis bald
    akari



  • Probleme kommen auf, wenn man jetzt z.b. ein Array speichern will.

    struct TFtpServer 
    { 
       AnsiString Username; 
       AnsiString Password; 
       AnsiString Ip; 
       short      port 
       bool       Ascii; 
    } 
    
    // Klasse zum verwalten der optionen. 
    class TOptionen 
    { 
       private: 
       public: 
    
          //Ftp Server Daten 
          TFtpServer FtpServerListe[20];  /* Hier würd ich z.b. gerne 20 Server 
                                             speichern. */
          /* ... */
          void SaveToIni();
          bool LoadFromIni();
    };
    

    Wie würdest du das jetzt speichern? Ne Zählschlafe in der SaveToIni() und
    LoadFromIni() die dann so irgendwie aussieht:

    TOptionen::SaveToIni()
    {
    
       /* ... */
    
       for(int i=0; i < 20; i++)
       {
          ini->WriteString(  "FtpServer" + IntToStr(i), "Username", this->FtpServer[i].Username);
          ini->WriteString(  "FtpServer" + IntToStr(i), "Password", this->FtpServer[i].Password);
          ini->WriteString(  "FtpServer" + IntToStr(i), "Ip",       this->FtpServer[i].Ip;
          ini->WriteInteger( "FtpServer" + IntToStr(i), "Port",     this->FtpServer[i].port);
          ini->WriteBool(    "FtpServer" + IntToStr(i), "Ascii",    this->FtpServer[i].Ascii);
       }
    
       /* ... */
    }
    

    Oder gibts da was eleganteres?

    Wäre auch dankbar, wenn du mir mal den Trick verraten würdest, wie ich mit
    einem fstream einen AnsiString laden und speichern kann ohne in ihn einen fixen
    char zu packen.

    danke 😉



  • Weiß nicht was an der Lösung für ein Array jetzt so unelegant wäre.
    Das ist so ziemlich das Beste was du machen kannst.
    Allerdings würde ich einen Wert in der ini abspeichern der vielleicht max_count heißt und die Anzahl der Array-Elemente enthält.
    Das wäre dann wirklich elegant gelöst 😉


Anmelden zum Antworten