Entwickler-Ecke
Dateizugriff - 'xx: File of yy' speichern und Laden
MathiasH - Mi 31.07.02 14:32
Titel: 'xx: File of yy' speichern und Laden
Die Frage musste eigentlich denkbar einfach sein aber ich hab in der Delphi-Hilfe nichts entsprechendes gefunden, und meinen Borland handbuchsatz hab ich grad verliehen, also:
wie speichert/oder ladt man einen Record damit am simpelsten?
es soll ungefähr so aussehen:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| // #laden des file
#Settings := SettingsFile;
Settingsfile := Settings; // #speichern des file # |
geht das überhaupt so? (Ich hoffe doch)
MathiasH
Klabautermann - Mi 31.07.02 14:37
Hallo,
ein bisschen anders sieht das schon aus. Dein stichwort heßt
Typisierte Dateien. Ein (altes) Beispiel kannst du dir
hier [
http://www.oitmann.de/prob/TypFileDemo.zip] runterladen. Dort werden so ziemlich alle grundlegenden Operationen verwendet. Solltest du Delphi < 6 haben wird es sich über eine Unit in der uses Klausel beschweren, diese kann problemlos gelöscht werden.
Gruß
Klabautermann
GPF - Mi 31.07.02 15:57
Alternativ verwende besser die Registry bzw. Ini-Dateien um Einstellungen zu speichern.
Falls Du aber ein Record im ganzen direkt speichern möchtest benutze Streams. Hier ein kurzes Beispiel ohne irgendwelche Fehlerabfragen:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| var MyRecord: TMyRecord; //beliebiges Record const SettingsFilename='c:\MySettings.dat';
procedure LoadRecord; var fs: TFileStream; begin if not FileExists(SettingsFilename) then exit; FS:=TFileStream(SettingsFilename, fmOpenRead or fmShareDenyNone); //Datei öffnen FS.Read(MyRecord, SizeOf(MyRecord)); //Einlesen des Records FS.Free; end;
procedure SaveRecord; var fs: TFileStream; begin FS:=TFileStream(SettingsFilename, fmCreate or fmShareExclusive); //Datei öffnen FS.Write(MyRecord, SizeOf(MyRecord)); //Speichern des Records FS.Free; end; |
cbs - Mi 31.07.02 16:13
Tag auch
@GPF
das geht aber net wenn ich im record nen typ habe der in der größe undefiniert ist. zb. string ohne max. längenangabe
in diesem fall is TmyRecord ja nicht immer gleich groß
Klabautermann - Mi 31.07.02 17:24
Hallo,
GPF hat folgendes geschrieben: |
Alternativ verwende besser die Registry bzw. Ini-Dateien um Einstellungen zu speichern. |
Was findest du so schlim dran in eigene Dateien zu speichern? (hört sich böse an, meine ich aber nicht so ;))
Die Regestry sollte meiner Meinung nach nur in ausnahmefällen verwendet werden. Denn jeder eintrag in der Regestry macht dein Windows langsammer (besonders den start des selbigen).
@MathiasH
wenn du wie cbs mutmaßt Typen undefinierter länge in deinem Record hast kannst du auch Typisierte Dateien vergessen. In dem Fall währe es das einfachste, wenn du wie GPF vorschlägt ein INI-File verwendest. Diese würde ich der Regestry im normalfall vorziehen, da sie wesetlich unkomplizierter sind, damit meine ich gar nicht mal das erstellen und auslesen sondern viel mehr den umgang auch z.B. bei der Fehlersuche. Außerdem belasten sie dein System nicht.
Alternativ kanst du dir auch einen Eigenen Dateityp schaffen, der z.B.immer die länger deiner Daten mitspeichest. Hierzu währe das schlüsselword
Untypisierte-Dateien oder
tFileStream. Das ist dann aber ein stück aufwändiger (aber durchaus zu bewältigen).
Gruß
Klabautermann
GPF - Mi 31.07.02 17:41
Klabautermann, im Prinzip hast Du vollkommen recht. Ich kann es auch nicht leiden, wenn zuviele Programme die Systemregistrierung zumüllen. Mindestens ebenso schlimm ist die Speicherung der Daten als Ini Datei im Windows Ordner...
Dennoch hat diese Speicherung einen bedeutenden Vorteil:
Die interne Struktur ist vollkommen unwichtig. Änderst Du z.B. Dein Record aus welchen Gründen auch immer ab, so muß man erst einmal die alten Strukturen kennen und konvertieren. In der Systemregistrierung und bei den Ini Dateien existiert ein Schlüssel einfach nicht.
Es könnte ja auch passieren, daß Du aus welchen Gründen auch immer ein Datenfeld nicht mehr benötigst. Um zu den gespeicherten Daten kompatibel zu bleiben müßtest Du dieses Feld immer mit Dummyinhalten mitspeichern.
Abgesehen davon hat Microsoft die Registry eingeführt um die Ini Dateien abzulösen. Wenn ich die Win95 Richtlinien noch korrekt im Kopf habe (lange nicht mehr gelesen), so sind sämtliche Programme angewiesen nur noch die Systemregistrierung zu nutzen.
Zu dem Stringproblem bei typisierten Dateien bzw. bei meiner Streamlösung:
Typisierte Dateien haben
immer eine feste Struktur ähnlich den gängigen Datenbanksystemen. Ein String muß immer eine feste Länge haben (also z.B. String[99]). Die Speicherplatzverschwendung ist dabei zumeist immens.
Der große Vorteil bei den Streams ist, daß Du Deine Daten speichern kannst wie Du möchtest. Meine kurze oben angegebene Lösung funktioniert nur mit statischen Datentypen (feste Größe, keine Zeiger bzw. Verweise auf andere Datenstrukturen).
Um Strings mit dynamischer Länge speichern bzw. Laden zu können mußt Du erst einmal die Längeninformationen eines Strings mit speichern, damit Du dann soviel Speicherplatz für den String reservieren kannst und den Inhalt mit den Daten füllst.
Ein kurzes Beispiel dazu findest Du in dem Foreneintrag "TFileStream" von mir. Hier der Direktlink:
http://www.auq.de/viewtopic.php?p=4694&highlight=#4694 - Danke cbs für den Hinweis
Klabautermann - Mi 31.07.02 18:01
GPF hat folgendes geschrieben: |
Klabautermann, im Prinzip hast Du vollkommen recht. Ich kann es auch nicht leiden, wenn zuviele Programme die Systemregistrierung zumüllen. Mindestens ebenso schlimm ist die Speicherung der Daten als Ini Datei im Windows Ordner... |
Ja, da gehören sie auch wirklich nicht hin. Ich finde INI-Dateien im Programmverzeichnis allerdings sehr Praktisch, da sie, wie du erwähnt hast, äußerst flexibel sind. Außerdem ermöglicht dieses vorgehen ein Programm mit mehreren Komfigurationen paralel zu nutzen (einfach INI-Datei austauschen oder Programm mit unerschiedlichen INIs in unterschiedlichen Ordnern betreiben). Dies kann grade auf Entwicklersystemen interessant sein.
GPF hat folgendes geschrieben: |
Abgesehen davon hat Microsoft die Registry eingeführt um die Ini Dateien abzulösen. Wenn ich die Win95 Richtlinien noch korrekt im Kopf habe (lange nicht mehr gelesen), so sind sämtliche Programme angewiesen nur noch die Systemregistrierung zu nutzen. |
Ja, und in manchen Fällen ist es auch sinvoll diese zu nutzen (z.B. das Programm soll aus jedem Verzeichnis [von wechselmedien] immer mit der gleichen Konfiguration starten). Andererseits sollte man auch Microsoft richtlinien nich übernehmen ohne ihre brauchbarkeit auf das eigene ganz konkrete Projekt zu überprüfen.
GPF hat folgendes geschrieben: |
Um Strings mit dynamischer Länge speichern bzw. Laden zu können mußt Du erst einmal die Längeninformationen eines Strings mit speichern |
Oder ein endeZeichen für Strings definieren. Wenn man sich an C-Strings orientiert währe dies #0. In dem Fall muss man naturlich ausschließen können, das dieses Zeichen auf "natürliche" Weise vorkommen kann.
Gruß
Klabautermann
Eisenherz - Mi 31.07.02 20:31
GPF hat folgendes geschrieben: |
Dennoch hat diese Speicherung einen bedeutenden Vorteil:
Die interne Struktur ist vollkommen unwichtig. Änderst Du z.B. Dein Record aus welchen Gründen auch immer ab, so muß man erst einmal die alten Strukturen kennen und konvertieren. In der Systemregistrierung und bei den Ini Dateien existiert ein Schlüssel einfach nicht.
Es könnte ja auch passieren, daß Du aus welchen Gründen auch immer ein Datenfeld nicht mehr benötigst. Um zu den gespeicherten Daten kompatibel zu bleiben müßtest Du dieses Feld immer mit Dummyinhalten mitspeichern. |
Aus diesen Gründen und damit es einfach wird auch z.B. Bilder abzuspeichern habe ich mir eigene Klassen geschrieben, die
frei verfügbar [
http://www.kasparsoft.de/RakBinaryStreamData/index.htm] sind. Für diese Klassen gibt es auch ein eigenes
Tutorial [
http://www.kasparsoft.de/RakBinaryStreamData/Tutorial/index.html].
MathiasH - Fr 02.08.02 09:38
ich möchte es für die Konfiguration meines progis nutzen, d.h es speichert ca 200 Variablen(keine Strings, nur Integer, Color, Extended, Point)
diese Variablen sind im record Settings auf zwei unterrecords asufgeteilt
Ich bevorzuge im moment den weg mit file of, aber dieser Weg gibt mir ein Problem bei der Ersterstellung auf das dazu führ, dass die gesammte IDE abstürzt :evil:
PS.: ini-Files mag ich hier nicht so gern, weil die bei 200 vars reichlich umständlich sind :wink:
MathiasH
MathiasH - Fr 02.08.02 09:46
ach ja ein statisches array (1..16)mit Farbwerten ist noch enthalten, aber das dürfte eigentlich kein Problem sein.
Und ich hab mir den Code von GFB angeschaut-gleiches Problem: :!: Ersterstellung :!:
MathiasH[/u]
Klabautermann - Fr 02.08.02 11:39
Hallo,
MathiasH hat folgendes geschrieben: |
Ich bevorzuge im moment den weg mit file of, aber dieser Weg gibt mir ein Problem bei der Ersterstellung auf das dazu führ, dass die gesammte IDE abstürzt :evil: |
was amchst du? Eine solche reaktion hatte ich nie (nichtmal wenn ich nicht exestente Dateien öffnen wollte).
Grade der öffnen bzw. anlegen vorgang ist aber sehr Krittisch, deshalb solltest du ihn mehrfach sichern. Da das Demo nur die grundlegene Technik vorstellen sollte ist dort nur eine Überprüfung auf existens implementeirt (sollte ich vieleicht mal ensprechend erweitern).
Zusätzlich solltest du noch ein Prüfung per IOResult implementieren und die schreib/leseprossesse in eine
TRY EXCEPT Klausel Betten:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| f : FILE OF MyRecord; begin TRY AssignFile(f, 'C:\Test.DAT'); {$i-} Reset(f); {$i+} IF IORESULT = 0 THEN BEGIN // Kein fehler beim öffnen TRY Read(f, MyOptionsset); EXCEPT ShowMessage('Fehler beim besen'); END; // TRY EXCEPT CloseFile(f); END; [...] |
Gruß
Klabautermann
MathiasH - Fr 02.08.02 19:39
Der Fehler passiert ja nicht gleich beim öffnen sondern erst dann, wenn ich Settings0 auslese, ich bin mir nicht ganz sicher, aber es ist möglich, dass dieser Fehler durch einen zugriff auf TSettings erfolgt, aber wenn ich die sach mit F7 laufen lasse stürtzt die IDE erst ab, wenn ich F9 drücke
Stimmt auf try except hätt' ich eigentlich selber kommen können :oops:
PS hast du schon runde 10 bekommen, die Fehlt bei mir :!: :!: :!: :!: :!:
MathiasH
Klabautermann - Fr 02.08.02 23:34
MathiasH hat folgendes geschrieben: |
aber es ist möglich, dass dieser Fehler durch einen zugriff auf TSettings erfolgt, aber wenn ich die sach mit F7 laufen lasse stürtzt die IDE erst ab, wenn ich F9 drücke |
Setze eine Breakpoint. Wohin liest du den Inhalt der Datei? Hast du Speicher Reserviert? Sind Daten in der Datei?
Gruß
Klabautermann
MathiasH - Sa 03.08.02 10:04
Also ich nehme mal an, die Datei ist noch komplett leer, und eingelesen Werden die Daten in einen normalen Record(Settings: TSettings)
PS auch mit Breakpoint hatcht der Fehler erst, wenn ich ihn richtig starte!
Wahrscheinlich muss ich doch alles mit Ini machen, ist zwar suviel Arbeit aber es geht wenigstens!
MathiasH
Klabautermann - Sa 03.08.02 12:37
Hallo,
lese nur aus der Datei, wenn du nicht an deren Ende Bist:
Quelltext
1: 2:
| IF NOT EOF(f) THEN Read(f, MyVariable); |
Kannst ja mal ein wenig Code sehen lassen dann können wir leichter Fehler Finden.
Gruß
Kalabautermann
MathiasH - Sa 03.08.02 13:20
Ok da kommen die Code Fitzel:
1. Öffnen
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure cast_set_file; var filename: string; begin FileName := ExtractFilePath(Application.ExeName) + 'settings.dat'; AssignFile(savefile, FileName);
IF FileExists(FileName) THEN // Wenn die Datei existiert... Reset(savefile) // ...Öffnen ELSE // ansonsten... ReWrite(savefile); // ...Anlegen und Öffnen end; |
2.Schließen
3.Load Settings
Quelltext
1: 2: 3: 4: 5:
| procedure load_settings; begin seek(savefile, 0); read(savefile, Settings); end; |
4.saveSettings
Quelltext
1: 2: 3: 4: 5:
| procedure save_settings; begin seek(savefile, 0); write(savefile, Settings); end; |
5. Zuweisen der settings an optionsform: (beim zuweisen finden die Fehler statt obwohl die werte von settings recht vernümftig sind)
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| procedure settings_to_form; var i: integer; begin { for i := 1 to 16 do begin optionsform.ValueList.Cells[1, i] := colortostring(settings.Colors.graph[i]); end;
optionsform.Colorbox1.Selected := settings.Colors.x_axis; optionsform.Colorbox2.Selected := settings.Colors.y_axis; optionsform.Colorbox3.Selected := settings.Colors.x_axis_marks; optionsform.Colorbox4.Selected := settings.Colors.y_axis_marks; optionsform.Colorbox5.Selected := settings.Colors.x_axis_numbers; optionsform.Colorbox6.Selected := settings.Colors.y_axis_numbers; optionsform.Colorbox7.Selected := settings.Colors.zero; optionsform.Colorbox8.Selected := settings.Colors.dots;
optionsform.check_dots.Checked := settings.General.show_dots; optionsform.check_numbers.Checked := settings.General.show_numbers; optionsform.x_dest_edit.text := floattostr(settings.General.mark_distance_x); optionsform.y_dest_edit.text := floattostr(settings.General.mark_distance_y); optionsform.Edit_zoom_x.Text := floattostr(settings.General.zoom_x); optionsform.Edit_Zoom_y.Text := floattostr(settings.General.zoom_y); optionsform.Edit_mov_x.Text := inttostr(settings.General.mov_x); optionsform.Edit_mov_y.Text := inttostr(settings.General.mov_y);
end; |
und aufgerufen werden diese Schnipsel von F1.Create: (das settings to form hab ich verlegt, weil optionsform noch nicht existierte, aber auch mit activat gehts nicht)
Quelltext
1: 2: 3:
| Cast_set_file; Load_Settings; settings_to_form; |
und von F1.Close:
Quelltext
1: 2:
| save_settings; Destroy_set_file; |
das wärs, und irgendwo ist da der Wurm drin
MathiasH
Klabautermann - Do 22.08.02 09:52
Hallo,
sorry das Posting ist ein wenig untergegangen nachdem ich ein paar Tage weg war.
Der Code sieht soweit ich das überblicken kann recht gut aus.
unter 3. würde ich noch die Sicherheitsabfrage aus meinem letztem Posting einbauen:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| function load_settings : Boolean; begin Result := FALSE; seek(savefile, 0); IF NOT EOF(saveFile) THEN BEGIN read(savefile, Settings); Result := TRUE; END; end; |
und entsprechend die Daten nur dann zuweisen wenn die Function True zurückgibt.
Quelltext
1: 2: 3:
| Cast_set_file; IF Load_Settings THEN settings_to_form; |
Gruß
Klabautermann
MathiasH - Fr 23.08.02 09:31
mittlerweile hab ich sowas eingebaut, aber da der Fehler jedes mal passiert werden die Eigenschaften nie geladen und er zeigt mir meine (eigene) Fehlermeldung: 'Fehler bei der Initialisierung'
Das Resultat: die Eigenschafts Datei ist nutzlos, da sie keine abrufbaren Variablen ausgibt :cry:
Ich vermute, man müsste diesen ersten *Datensatz* ersteinmal createn, bevor man auf ihn zugreift, aber wie
MathiasH
ugoldhan - So 20.10.02 17:43
Titel: INI Dateien müssen nicht das Windows-Verzeichnis zumuellen!
Hi,
weiter oben lese ich, dass das Zumuellen des Windowsverzeichnisses mit INI's ein Problem wäre. Das passiert nur, wenn der Pfad zur INI nicht angegeben wird. Es sind bereits genügend Beispiele auf den Boards, die sich um das Thema ExtractFilepath in Kombination mit Application.ExeName bzw. ParamStr(0) drehen.
Gruss von Uwe
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!