Autor Beitrag
MathiasH
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 699

WinXP, Win98SE, Debian, Win95
D5 Stand, D6 Prof
BeitragVerfasst: Mi 31.07.02 14:32 
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:

ausblenden 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

_________________
"Viel von sich reden, kann auch ein Mittel sein, sich zu verbergen."
Friedrich Nietzsche
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 85



BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 207
Erhaltene Danke: 1



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 85



BeitragVerfasst: 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: www.auq.de/viewtopic...&highlight=#4694 - Danke cbs für den Hinweis
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 48



BeitragVerfasst: 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 sind. Für diese Klassen gibt es auch ein eigenes Tutorial.

_________________
aloa Eisenherz
MathiasH Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 699

WinXP, Win98SE, Debian, Win95
D5 Stand, D6 Prof
BeitragVerfasst: 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

_________________
"Viel von sich reden, kann auch ein Mittel sein, sich zu verbergen."
Friedrich Nietzsche
MathiasH Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 699

WinXP, Win98SE, Debian, Win95
D5 Stand, D6 Prof
BeitragVerfasst: 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]

_________________
"Viel von sich reden, kann auch ein Mittel sein, sich zu verbergen."
Friedrich Nietzsche
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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:

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 699

WinXP, Win98SE, Debian, Win95
D5 Stand, D6 Prof
BeitragVerfasst: 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

_________________
"Viel von sich reden, kann auch ein Mittel sein, sich zu verbergen."
Friedrich Nietzsche
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 699

WinXP, Win98SE, Debian, Win95
D5 Stand, D6 Prof
BeitragVerfasst: 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

_________________
"Viel von sich reden, kann auch ein Mittel sein, sich zu verbergen."
Friedrich Nietzsche
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Sa 03.08.02 12:37 
Hallo,

lese nur aus der Datei, wenn du nicht an deren Ende Bist:

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 699

WinXP, Win98SE, Debian, Win95
D5 Stand, D6 Prof
BeitragVerfasst: Sa 03.08.02 13:20 
Ok da kommen die Code Fitzel:

1. Öffnen
ausblenden 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
ausblenden Quelltext
1:
CloseFile(savefile);					


3.Load Settings
ausblenden Quelltext
1:
2:
3:
4:
5:
procedure load_settings;
begin 
seek(savefile, 0);
read(savefile, Settings);      
end;


4.saveSettings
ausblenden 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)
ausblenden 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)
ausblenden Quelltext
1:
2:
3:
Cast_set_file;
Load_Settings;
settings_to_form;


und von F1.Close:
ausblenden Quelltext
1:
2:
save_settings;
Destroy_set_file;


das wärs, und irgendwo ist da der Wurm drin

MathiasH

_________________
"Viel von sich reden, kann auch ein Mittel sein, sich zu verbergen."
Friedrich Nietzsche
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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:

ausblenden 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.

ausblenden Quelltext
1:
2:
3:
Cast_set_file;
IF Load_Settings THEN
  settings_to_form;


Gruß
Klabautermann
MathiasH Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 699

WinXP, Win98SE, Debian, Win95
D5 Stand, D6 Prof
BeitragVerfasst: 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

_________________
"Viel von sich reden, kann auch ein Mittel sein, sich zu verbergen."
Friedrich Nietzsche
ugoldhan
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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