Was sind heute gängige Verfahren, um Einstellung in einem simplen Programm zu speichern (C++)? InI Datei? SQL Datenbank (z.B. eine kleine SQLite)? Regedit? Was wäre das Pendant unter Linux? Oder gibt es da inwzischen einfachere Lösungen?
Was sind "Einstellungen"? Wie viele, welche Komplexität haben diese (sind das einfache numerische Werte, sind das komplexe Datenstrukturen o.ä.), wie fehlertolerant darf/muss das Abspeichern/Einlesen sein, welches Betriebssystem, welche Programmiersprache? Sollen die "Einstellungen" auch transportiert werden können, oder sollen/dürfen die auf dem individuellen Rechner verbleiben?
Eine Datenbank für (vermutlich) eine handvoll Einstellungen ist wohl etwas over-the-top. Aber es gibt standardisierte Formate wie XML, YAML oder JSON die weit verbreitet sind.
Ini mag oldstyle klingen, aber ich bin damit immer gut gefahren. https://stackoverflow.com/questions/217902/reading-writing-an-ini-file
Max M. schrieb: > Regedit? Was wäre das Pendant unter Linux? Das währe dann wohl gsettings/dconf (ehemals gconf). Ist aber eine reine Gnome Geschichte, und nur für Benutzer-/Desktop- Anwendungen. Nicht alle mögen es, die meisten Programme schreiben ihre Sachen einfach als File in XDG_CONFIG_HOME https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html (Der Default ist normalerweise ~/.config/ für die User Settings und /etc/xdg/ Systemweit) (Dort gibt es übrigens auch das dconf Verzeichnis).
:
Bearbeitet durch User
Max M. schrieb: > Was sind heute gängige Verfahren, um Einstellung in einem simplen > Programm zu speichern (C++)? JSON-Dateien sind ganz vorne dabei, würde ich sagen. XML soll ja schon wieder tot sein ... ;) > InI Datei? Kann man machen, ist aber manchmal dann doch zu einfach gestrickt. > SQL Datenbank (z.B. eine kleine SQLite)? Kanonen -> Spatzen. > Regedit? Würde ich eher nicht machen (es sei denn, es existieren sehr spezielle Gründe dafür). - Geht nicht unter Linux. - Die Einstellungen können nicht einfach kopiert werden. - Leichen können in der Registry verbleiben. - ... Schau dir das mal an: https://github.com/nlohmann/json Ist plattformunabhängig und man muss nur eine Headerdatei einbinden. > Oder gibt es da inwzischen einfachere Lösungen? Selber basteln würde ich das jedenfalls nicht mehr. Es muss ja nicht nur irgendwie funktionieren, sondern sollte auch möglichst einfach und elegant zu verwenden sein. Die Werte, die man speichern und einlesen will, haben meist unterschiedliche Typen, was sich mit einer streng typisierten Sprache u.U. etwas beißen kann ... Und dies ist nur eines von mehreren Problemen, um die man sich kümmern muss. Das ist schon ein kleines Projekt für sich, wenn man es vernünftig machen will.
Michael K. schrieb: > Ist plattformunabhängig und man muss nur eine Headerdatei einbinden. Man sollte sich allerdings Gedanken darum machen, wo man die Datei unterbringt. Das unterscheidet sich von Betriebssystem zu Betriebssystem doch erheblich.
Die einfachste Lösung dürfte auch die älteste sein, der Inhalt des relevanten Speicherbereichs wird binär so wie er ist in eine Datei geschrieben, die beim Programmstart wieder in den Speicher geladen werden kann. Den ganzen anderen Quatsch braucht man nur wenn es für den Menschen einfach lesbar sein soll oder man ein bestimmtes Dateiformat erzeugen möchte, das möglicherweise kleiner wird als der abzubildende Speicherbereich, etwa weil nicht alle Variablen eines Programms gespeichert werden sollen. Bzw. eine Initialisierungsdatei wie
1 | Schalter1=an |
2 | Schalter2=aus |
3 | Schalter3=an |
4 | Schalter4=aus |
5 | Schalter5=an |
6 | Schalter6=aus |
7 | Schalter7=an |
8 | Schalter8=aus |
hat für einen Computer genau so viel Informations-Gehalt wie ein einzelnes Byte.
:
Bearbeitet durch User
Ben B. schrieb: > Die einfachste Lösung dürfte auch die älteste sein, der Inhalt des > relevanten Speicherbereichs wird binär so wie er ist in eine Datei > geschrieben, die beim Programmstart wieder in den Speicher geladen > werden kann. Funktioniert halt nur, wenn der "relevante Speicherbereich" so strukturiert ist, daß er tatsächlich aus einem zusammenhängenden Block besteht. Und hat den schönen Reiz, daß es knallt, falls die Struktur des Speicherbereichs durch eine geänderte Programmversion verändert wird. Ohne Versionierung ist so eine Binärdatei also eine leckere Fehlerquelle.
Ben B. schrieb: > Den ganzen anderen Quatsch braucht man nur wenn es für den Menschen > einfach lesbar sein soll Wenn da irgendein Mumpitz drinsteht, der die Anwendung gnadenlos abstürzen läßt, dann ist man doch heilfroh, wenn man es editieren kann. Binärdaten hat man vielleicht benutzt, als die Programme noch auf eine 160kB 5,25" Diskette passen mußten.
Zuerst wäre zu klären WO die Preferenzen gesichert werde sollen. Jedes OS hat dafür m.W einen speziellen Systemordner, sowas wie system.specialfolder.preferences (global) oder userspezifisch. Dann gibts noch die Möglichgkeit, die Daten bei der Anwendung (im selben Ordner) zu sichern. Das ist sinnvoll, wenn die Anwendung nicht speziell "installiert" werden muss, sondern portable ist. Ich habe mir für Xojo eine Preferences-Klasse selber gemacht, die kann Integer, Double, String, Boolean und Color sichern und wieder laden. Der Speicherort und der Name der Datei werden im Constructor übergeben. Beim Sichern gehe ich ungefähr so vor: mypref.addStr("dbname", dbname.text) mypref.save (ganz am Ende) also Key-Value-Prinzip. Beim Laden entsprechend umgekehrt: dbname.text = mypref.getStr("dbname") Verschlüsseln tu' ich es nicht, aber mit Base64 gegen Encoding-Fehler und all zu große Offensichtlichkeiten verpacken. ...
:
Bearbeitet durch User
Er wollte eine möglichst einfache Möglichkeit wissen. Nichts für mehrere verschiedene Programmversionen oder sonstige Übertragbarkeit. > Wenn da irgendein Mumpitz drinsteht, > der die Anwendung gnadenlos abstürzen läßt [..] Das ist kein Argument. Das kann bei einer .ini-Zeile wie "Zahl=hahalustig" genau so passieren wenn das Programm nicht auf solche Spaßvögel vorbereitet ist. Vielleicht kannst Du so einen Fehler noch beheben weil Du Dich für die Programmierung interessierst und solche Dateien lesen kann. Der 0815-Dau weiß aber nicht mal was eine .ini ist und kommt gar nicht erst auf die Idee, sich das mal genauer anzuschauen.
Ben B. schrieb: > Das ist kein Argument. Das kann bei einer .ini-Zeile wie > "Zahl=hahalustig" genau so passieren wenn das Programm nicht auf solche > Spaßvögel vorbereitet ist. Nö. Ini-Dateien werden (sofern man die dafür vorgesehenen API-Funktionen verwendet) gezielt nach Key-Value-Paaren abgefragt. Wenn da zusätzliches Geraffel drinsteht, stört das nicht, denn der wird gar nicht erst gelesen. Ein
1 | int bla; |
2 | |
3 | bla = GetPrivateProfileInt("Meinkram", "Meinwert", 0, meineinidatei); |
liest folgenden Inhalt:
1 | |
2 | [Meinkram] |
3 | Meinwert=123 |
Existiert die Datei nicht, steht in der Datei kein Abschnitt "Meinkram" drin, gibt es keine Zeile "Meinwert=", gibt die Funktion den Wert 0 zurück. Damit kann man ein sicheres Defaultverhalten herbeiführen, man muss nur noch sicherstellen, daß der Wert insgesamt in einem sinnvollen Wertebereich liegt. Das aber ist's dann auch schon. Und gespeichert wird das ganze so:
1 | int bla; |
2 | |
3 | bla = 234; |
4 | |
5 | WritePrivateProfileInt("Meinkram", "Meinwert", bla, meineinidatei); |
Das einzige, worum man sich kümmern muss, ist das Bestimmen des in den Beispielen "meineinidatei" genannten Dateinamens und -Pfades. Und man sollte einen Blick in die API-Dokumentation von MS reinwerfen.
:
Bearbeitet durch User
Na, wer moechte das "leserlich" dekodieren? Bonusfrage: Ist von welchem Programm?
Michael K. schrieb: > JSON-Dateien sind ganz vorne dabei, würde ich sagen. > XML soll ja schon wieder tot sein JSON auch. Der neue heiße Scheiß sind YAML Dateien. Eine Datenbank würde ich nur verwenden, wenn das Programm aus anderen Gründen eh schon eine Datenbank hat. Ansonsten bin ich ein Freund von Text-basierten Dateien, die man manuell bearbeiten kann, wenn es mal sein muss.
:
Bearbeitet durch User
Harald K. schrieb: > Was sind "Einstellungen"? Wie viele, welche Komplexität haben diese > (sind das einfache numerische Werte, sind das komplexe Datenstrukturen > o.ä.), wie fehlertolerant darf/muss das Abspeichern/Einlesen sein, > welches Betriebssystem, welche Programmiersprache? > > Sollen die "Einstellungen" auch transportiert werden können, oder > sollen/dürfen die auf dem individuellen Rechner verbleiben? Nichts besonderes, das hätte ich ansonsten erwähnt. Vollkommener Standard, Zahlen, Strings. Parameter z.B. für eine CNC o.ä. Michael K. schrieb: > JSON-Dateien sind ganz vorne dabei, würde ich sagen. XML soll ja schon > wieder tot sein ... ;) JSON finde ich persönlich ganz schlimm. Im Endeffekt JSON, XML, INI, binär (ganz sicher nicht). Vermutlich werde ich es ganz altmodisch mit ini versuchen. Wo speichern denn Programme wie z.B. KiCad ihre Parameter?
Max M. schrieb: > Wo speichern denn Programme wie z.B. KiCad ihre Parameter? Siehe Screenshot. Es sind überwiegend JSON Dateien, aber auch ein paar andere.
:
Bearbeitet durch User
Ich würde das auch in JSON machen, da es auch plattformübergreifend (UTF-8) ist. Da gibt es bestimmt auch Libraries für C++ und Linux, falls du mit Linux arbeitest. Und viel schwerer, als mit einer .ini Datei ist es auch nicht. Also für ein paar Einstellungen ideal. Dazu kommt noch, daß man mit JSON Listen, deren Größe vorher noch unbestimmt ist, erzeugen und erweitern kann. {} = Objekt [] = Liste Für ein paar Einstellungen genügt da ein Haupt-Objekt und darin die Werte : "Schlüssel" : Wert|"Wert"|BOOL Also ganz einfach : {"Maschine" : "Stand1", "Datum" : "27.04.2023", "Startwert" : 100, "Parameter" : ["einString", 100, 0, 1]} Wie man sieht, kann man in einer Liste auch Strings, Zahlen oder boolsche Werte mischen. Dafür braucht man ja keine .zig Objekt-Ebenen zum Durchhangeln. Und wenn man mehrere Maschinen hat, muß man halt zuerst ein oberes Objekt (z.B. Maschinen) erzeugen und darin halt die Unterobjekte. Mittlerweile arbeite ich ganz gerne mit JSON. PS: Übrigens kannst du das auch mit SQLITE3 (Vers. 3.38) machen, wenn deine Sprache SQL-Statements (SQLEXEC) unterstützt : https://www.sqlite.org/json1.html
:
Bearbeitet durch User
Back to the roots. Die besten Zeiten waren die, wo man Programme einfach kopieren konnte, also alle Einstellungen ebenfalls im gleichen Ordner wie das Programm lagen. wenn es keinen zwingenden Grund gibt, weil z.B. ANDERE Programme von der Existenz deine Programms und womöglich dessen Optionen, wissen müssen, gibt es gar keinen Grund und finde es sogar extrem Kontraproduktiv, solche Informationen in irgendwelchen Registries abzulegen Und wegen irgenwelcher Backup ist es ach ein wirkliches Argument
Für Einstellungen bevorzuge ich nach wie vor XML. Das ist auch plattformübergreifend und hat vor allem den Vorteil, dass man es einfach validieren kann. Mit XPath und XQuery sind auch einfache Abfragen möglich. Außerdem geben viele Editoren direkt Hinweise, wenn die Datei formal nicht richtig ist, falls man die Daten einmal manuell korrigieren muss. Dass es etwas größer ist als JSON, stört mich kaum. Die Dateien, um die es bei mir geht, sind meistens recht klein (maximal ein paar kB), nur wenige haben dann tatsächlich einmal mehrere MB. Ebenso kann ich gut damit leben, dass XPath Abfragen nicht besonders performant sind - der Komfortgewinn beim Programmieren gleicht das allemal aus; vor allem, wenn diese Abfragen uim Programm nicht häufig benutzt werden (wie es bei Konfigurationsdaten normalerweise der Fall ist).
> Nö. Ini-Dateien werden (sofern man die dafür vorgesehenen > API-Funktionen verwendet) gezielt nach Key-Value-Paaren abgefragt. > [..] Das ist immer noch kein gutes Argument bzw. Du verlässt Dich halt auf eine vorgefertigte API oder ein anderes Interface (wie auch z.B. ein MySQL-Server eines wäre), was entsprechend gegen Vergewaltigung der gespeicherten Daten gehärtet ist. Das kann man natürlich machen, aber wenn man den Parser selbst schreibt oder ein eigenes Dateiformat verwendet, muss man sich auch selbst um solche Fehlerquellen kümmern und erlebt sehr merkwürdige Effekte, wenn man es nicht tut.
Peter K. schrieb: > Die besten Zeiten waren die, wo man Programme einfach kopieren konnte, > also alle Einstellungen ebenfalls im gleichen Ordner wie das Programm > lagen. Das waren die schlimmsten Zeiten. Da hat jeder Hinz und Kunz irgendwelchen Rotz irgendwo abgelegt, und man musste sich mühsam diesen ganzen Krempel zusammensuchen, wenn man es auf einen anderen Rechner übertragen wollte. Das Konzept, alle von einem Benutzer erzeugten Dateien in einem Verzeichnisbaum unterzubringen, der dem Benutzer gehört, ist da deutlich besser -- dann können auch mehrere Leute mit einem Computer arbeiten, ohne durcheinanderzukommen. Wenn die Lebensabschnittsbegleiterin gerne ihre Textdokumente in "Comic Sans" verfasst und die Standardformatvorlage so konfiguriert, muss man sich nicht drüber ärgern, denn man hat seine eigene Standardformatvorlage mit einer Schriftart für Erwachsene.
Heinz B. schrieb: > Ich würde das auch in JSON machen, da es auch plattformübergreifend > (UTF-8) ist. Da gibt es bestimmt auch Libraries für C++ und Linux, > falls du mit Linux arbeitest. Mann muss dann einfach daran denken, dass man Binärdaten dann vorher z.B. base64 Kodiert / Dekodiert. Und in C kann man Strings mit beliebigen Byte folgen haben, z.B.
1 | const char mymessage[] = "Hello\xFFWorld"; |
Wenn man das direkt als JSON String speichert, ist das \xFF kein gültiges Zeichen. Vielleicht ist der Encoder noch so clever, es wenigstens durch den Codepoint für ungültiges Zeichen zu ersetzen (\xEF\xBF\xBD) oder so, statt ungültiges JSON zu erstellen, aber das Zeichen so wieder Dekodieren wird nichts. Ausserdem ist JSON eine Art Baumstruktur. Grafen, ala A.b=B B.a=A kann man darin nicht direkt abbilden, das muss man dann auch manuell anders darstellen.
Ja das ist auch so eine Unart, daß jeder sein eigenes Stringformat oder Zeichensatz bis UTF-65536 benutzt nur weil er denkt, das wäre cool. Deswegen bin ich bei meinen Datenbankprojekten schon lange dazu übergegangen, solchen Quatsch einfach komplett "escaped" wegzuspeichern. Wenn die search engine der Datenbank dann irgendwas nicht wiederfindet weil mit solchen Sonderzeichen rumgespielt werden musste - nicht mein Problem. Ein Leerzeichen, wie man es für "Hello World!" benötigt, ist ASCII 32 - und nicht 255. Keine Ahnung, wieso man in normalem Fließtext 255 benutzen sollte, außer man möchte das Programm ärgern.
Die meisten Datenbanken kennen einen VARBINARY(N) Datentyp, analog zum VARCHAR(N). (Würde ich übrigens auch zum Speichern von Pfaden empfehlen, die müssen nämlich nicht unbedingt normalisiertes UTF-8 sein). Und analog zu TEXT gibt es BLOB. In DBs escape ich nichts manuell. Da nimmt man die prepared Statements die die DB Library anbietet, und die passenden Datentypen für die Daten. PS: Bei sqlite ist sowieso alles immer schnuppe. Datentypen, Foreign keys, etc. sind dort normalerweise nichts als blosse Suggestionen. Wobei man aber wenigstens ein paar Checks einschalten kann.
ALT+255 hatte ich damals zu MS-DOS Zeiten zum Verstecken von Dateien und dem DIR - Befehl benutzt. Wozu das man heute noch braucht ?
Ben B. schrieb: > Keine Ahnung, wieso man in normalem Fließtext 255 > benutzen sollte Als Non-Breaking space, damit verhindert man Zeilenumbrüche im Fließtext an Stellen an denen sie unerwünscht sind. Ist in UTF-8 allerdings nicht 255, sondern  . Zum Thema zurück: Wenn der TE für sein C++ eine GUI-Bibliothek verwendet, sollte er mal nachsehen, ob die nicht schon was passendes mitbringt. z.B. https://doc.qt.io/qt-5/qsettings.html Dann landen die Einstellungen auf jedem System in der dort üblichen Form am dort üblichen Platz... https://doc.qt.io/qt-5/qsettings.html#platform-specific-notes
Heinz B. schrieb: > Also ganz einfach : > > {"Maschine" : "Stand1", "Datum" : "27.04.2023", "Startwert" : 100, > "Parameter" : ["einString", 100, 0, 1]} Das Selbe sieht in Yaml so aus:
1 | Maschine: Stand1 |
2 | Datum: 27.04.203 |
3 | Startwert: 100 |
4 | Parameter: [einString,100,0,1] |
Oder alternativ so:
1 | Maschine: Stand1 |
2 | Datum: 27.04.203 |
3 | Startwert: 100 |
4 | Parameter: |
5 | - einString |
6 | - 100 |
7 | - 0 |
8 | - 1 |
Im Gegensatz zu JSON kann man YAML Dateien kommentieren.
:
Bearbeitet durch User
Hallo allerseits, Dennis S. schrieb: > Eine Datenbank für (vermutlich) eine handvoll Einstellungen ist wohl > etwas over-the-top. Armin K. schrieb: > Ini mag oldstyle klingen, aber ich bin damit immer gut gefahren. > > https://stackoverflow.com/questions/217902/reading-writing-an-ini-file wenn ich diese Beiträge lese, fühle ich mich komplett out-of-date.
Harald K. schrieb: > Das waren die schlimmsten Zeiten. Da hat jeder Hinz und Kunz > irgendwelchen Rotz irgendwo abgelegt, und man musste sich mühsam diesen > ganzen Krempel zusammensuchen, wenn man es auf einen anderen Rechner > übertragen wollte. Nein, so war das garnicht. Alles lag halt innerhalb (unterhalb) des Programmverzeichnisses. Und es war sogar völlig problemlos möglich, benutzerspezifische Einstellungen auf diese Art abzulegen. Ist nur ein Alptraum bezüglich der Sicherheit und Vertraulichkeit. Bezüglich des reinen Datenflusses geht das aber völlig problemlos. > Das Konzept, alle von einem Benutzer erzeugten Dateien in einem > Verzeichnisbaum unterzubringen, der dem Benutzer gehört, ist da deutlich > besser Natürlich erheblich besser bezüglich Sicherheit und Vertraulichkeit. Aber führt auch einen Haufen Overhead ein. Da ist zum einen das Thema: "Einstellungen, die ein User ABSICHTLICH (in guter Absicht!) mit anderen Usern teilen möchte. Und zum anderen: Einstellungen, die eine "übergeordnete Autorität" dem User unumgehbar aufzwingen möchte. Beides läßt sich mit dem Konzept der Home-Verzeichnisse nur schlecht bis garnicht abbilden.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.