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?
|
Anzeige
|
Einstellungen im Programm speichernWas 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
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).
JSON-Dateien sind ganz vorne dabei, würde ich sagen. XML soll ja schon wieder tot sein ... ;)
Kann man machen, ist aber manchmal dann doch zu einfach gestrickt.
Kanonen -> Spatzen.
Würde ich eher nicht machen (es sei denn, es existieren sehr spezielle Gründe dafür).
Schau dir das mal an: https://github.com/nlohmann/json Ist plattformunabhängig und man muss nur eine Headerdatei einbinden.
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.
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
hat für einen Computer genau so viel Informations-Gehalt wie ein einzelnes Byte.
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.
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. ... Er wollte eine möglichst einfache Möglichkeit wissen. Nichts für mehrere verschiedene Programmversionen oder sonstige Übertragbarkeit.
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.
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
liest folgenden Inhalt:
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:
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. Na, wer moechte das "leserlich" dekodieren? Bonusfrage: Ist von welchem Programm?
Gast
#7401306
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.
Nichts besonderes, das hätte ich ansonsten erwähnt. Vollkommener Standard, Zahlen, Strings. Parameter z.B. für eine CNC o.ä.
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?
Gast
#7401357
Siehe Screenshot. Es sind überwiegend JSON Dateien, aber auch ein paar andere. 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 :
Gast
#7401576
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).
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.
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.
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.
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 ?
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
Gast
#7401927
Das Selbe sieht in Yaml so aus:
Oder alternativ so:
Im Gegensatz zu JSON kann man YAML Dateien kommentieren. Hallo allerseits,
wenn ich diese Beiträge lese, fühle ich mich komplett out-of-date.
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.
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. Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|