Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Wie speichere ich einen String am besten? (https://www.delphipraxis.net/148154-wie-speichere-ich-einen-string-am-besten.html)

Salazriel 23. Feb 2010 19:45


Wie speichere ich einen String am besten?
 
Ich möchte dem Nutzer in meinem Sudoku-Programm die Möglichkeit geben, Sudokus zu speichern, z.B. damit man es nicht an einem Stück machen muss. Selbstverständlich soll es auch möglich sein, ein Sudoku zu laden.
Der Ansatz ist dabei der, dass das Sudoku in einem String gespeichert wird, die String[1] ist die Zahl links oben, String[10] die Zahl darunter.
Nach dem ich verschiedene Möglichkeiten abgewogen hat (sprich: entweder Ini oder Savedialog, aber ich will, dass der Nutzer so komfortabel wie möglich speichern und laden kann) möchte ich TSaveDialog und TLoadDialog benutzen. Auf Knopfdruck (nur Entwicklungsphase, packe ich später bei der Save-Prozedur rein) wird das Sudoku zeichenweise in eine Zeile eines TMemos gepackt, mögliche Zeichen sind halt '1'..'9' und ' '. In der Save-Prozedur soll diese Zeile gespeichert werden, in der Load-Prozedur soll aus der Datei der String ans TMemo geaddet werden. Dazu speichere ich eine TStringList als .txt-Datei.
Die TMemo dient dabei nur als visuelle Überprüfung, später reduziere ich das ganze auf TStringList.
Try und finally kommen später noch.


Delphi-Quellcode:
procedure TForm1.Speichern(Sender: TObject);
var Sudoku:TStringList;
begin
Sudoku:=TStringList.create;
SaveDialog1.Filter:='*.txt|*.TXT';
if SaveDialog1.execute
then
  begin
  Sudoku[0]:=Memo1.lines[0];
  Sudoku.SaveToFile(SaveDialog1.FileName);
  end;
Sudoku.Free;
end;



procedure TForm1.Sudokuladen1Click(Sender: TObject);
var Sudoku:TStringList;
begin
Sudoku:=TStringList.create;
OpenDialog1.Filter:='*.txt|*.TXT';
if OpenDialog1.execute
then
  Sudoku.LoadFromFile(OpenDialog1.FileName);
  Memo1.Lines.add(Sudoku[0]);
  end;
Sudoku.Free;
end;

Wenn ich aber versuche, ein Sudoku zu speichern, gibt er eine Fehlermeldung "Out of bound " aus.
Was mache ich falsch?

PS: Diese .txt-Datei ist ja sehr manipulationsanfällig (würde dem Nutzer nichts bringen, aber...), kann man das auch in einem Format schreiben, auf das der Nutzer nicht per Explorer öffnen kann?

[edit=SirThornberry]Titel korrigiert - Mfg, SirThornberry[/edit]

himitsu 23. Feb 2010 19:49

Re: Wie speichere ich am einen String am besten?
 
Wenn die StringList grade erst erstellt wurde, dann ist sie leer und es gibt keine Zeilen (hier die Zeile 0)

Delphi-Quellcode:
Sudoku.Add(Memo1.lines[0]);

Noedel 23. Feb 2010 20:53

Re: Wie speichere ich am einen String am besten?
 
[offtopic]
Wenn du nur Zahlen von 1-9 abspeicherst, hast du leere Felder übersprungen und du bekommst am Ende nicht das raus, was du eigentlich haben wolltest, sondern die Zahlen sind dann alle verschoben. Vielleicht noch eine "0" für ein leeres Feld ergänzen ;)
[/offtopic]

Salazriel 23. Feb 2010 21:10

Re: Wie speichere ich am einen String am besten?
 
Immer diese Flüchtigkeitsfehler :oops:

Hab jetzt den Quelltext verändert, so dass es klappt. Jedoch stehe ich jetzt vor dem nächsten Problem (wobei ich zugeben muss, dass ich TSaveDialog bisher nur für Bilder benutzt habe und daher nur mit Formaten wie Bmp oder JPEG gearbeitet habe): Und zwar kann man die Datei speichern, wenn man sie aber laden möchte, bemerkt man, dass sie nicht im .txt-Format gespeichert ist, sondern in einem "Datei"-Format. Da der Filter beim OpenDialog aber nur die vorher gespeicherten Sudokus anzeigen soll (wie siehts eigentlich mit einem selbst definierten Format .sud aus? Spontan hat es nicht funktioniert), diese aber in dem .txt-Format sind (wie ja eigentlich im SaveDialog-Filter deklariert) werden diese nicht im Dialog angezeigt.

Zwar lädt der Dialog bei korrekter Namensangabe das richtige Sudoku, aber diesen Namen sieht man im OpenDialog ja nicht wegen dem Filter.
Ich könnte das ganze filterlos machen, so dass alle Dateien im Ordner angezeigt werden, was zwar theoretisch ginge, da der Ordner ja dann im Ordner der Projektdatei sein soll, aber praktisch halte ich das ganze für... unelegant. :-D

Könnt ihr mir helfen, entweder ein Format .sud zu definieren und den Save-Filter zum Funktionieren bringen oder mir die Sache erklären?

PS: @Noedel Da hat mir doch jetzt jemand dazwischen gefunkt bei meinem kleinen Beitrag :-D.
Dein Tipp ist zwar sehr nett, aber an nicht ausgefüllten Stellen schreibt er ein ' '
und daher klappt das schon, aber trotzdem danke :)

Wobei ich gerade bemerke, das mir das Forum den Ausdruck 'Leerzeichen' zu '' verkürzt, bei PS
und im ersten Post soll es natürlich '*hierStehtEinLeerzeichen* heißen, aber naja...
Wie gesagt trotzdem danke :mrgreen:

haentschman 24. Feb 2010 08:05

Re: Wie speichere ich am einen String am besten?
 
Guten Morgen...
Zitat:

Der Ansatz ist dabei der, dass das Sudoku in einem String gespeichert wird, die String[1] ist die Zahl links oben, String[10] die Zahl darunter.
...ist vom Ansatz her wahrscheinlich schon nicht optimal. Du mußt deine "Felder" in einen String wandeln und dann wieder zurück. Wie verwaltest du die "Felder" während des Spiels ? Vieleicht läßt sich diese Datenstruktur direkt speichern ?

:hi:

p80286 24. Feb 2010 10:10

Re: Wie speichere ich am einen String am besten?
 
Zitat:

Zitat von haentschman
...ist vom Ansatz her wahrscheinlich schon nicht optimal. Du mußt deine "Felder" in einen String wandeln und dann wieder zurück. Wie verwaltest du die "Felder" während des Spiels ? Vieleicht läßt sich diese Datenstruktur direkt speichern ?

damit wäre dann auch eine gewisse Manipulationsverhinderung gegeben.

Da ich für mich nicht viel von diesen Dateinamenfiltern halte, verstehe ich die geistigen Klimmzüge nicht ganz, die Du um den Dateinamen machst. Nenn deine Dateien *.SOD, *.SUD, *.SDK oder wie auch immer, pass den Filter entsprechend an und gut ist.

Gruß
K-H

HeikoAdams 24. Feb 2010 10:44

Re: Wie speichere ich am einen String am besten?
 
Zitat:

Zitat von Salazriel
PS: Diese .txt-Datei ist ja sehr manipulationsanfällig (würde dem Nutzer nichts bringen, aber...), kann man das auch in einem Format schreiben, auf das der Nutzer nicht per Explorer öffnen kann?

Verschlüssel die .txt-Datei doch einfach und verpass ihr als Endung z.B. .sudoku - damit kann der Explorer erst mal nix anfangen, solange kein anderes Programm diese Endung für sich registriert hat :wink:

Die Muhkuh 24. Feb 2010 10:51

Re: Wie speichere ich am einen String am besten?
 
Meine Güte, es handelt sich um ein einfaches Sudoku, dass man auf dem PC spielt. Wenn jemand unbedingt an der Save-Datei rumfummeln will, lass ihn doch, ist ja sein Problem, wenn er sich dadurch den Spielspaß nimmt.

Salazriel 24. Feb 2010 15:41

Re: Wie speichere ich einen String am besten?
 
Erstmal vielen Dank für die große Resonanz. :mrgreen:

@haentschman
Den String erstelle ich mit
Delphi-Quellcode:
Memo1.clear;
Datei:='';
For Zeile:=0 to 8 do
  For Spalte:=0 to 8 do
    Datei:=Datei+StringGrid1.cells[Spalte,Zeile]; // in OnCreate wurde jedes Feld mit ' ' belegt
Memo1.Lines.Add(Datei);
und verarbeiten mit
Delphi-Quellcode:
For i:=1 to 81 do
  begin
  Spalte:=(i-1) mod 9;
  Zeile:=(i-1) div 9;  // i-1 da Zellen/Spalten von 0..8
  StringGrid1.Cells[Spalte,Zeile]:=Datei[i];
  end;
Ich verstehe jetzt nicht was daran so schwer sein soll? Oder habe ich einen Denkfehler, der das Problem unzulässig vereinfacht?


@p80286

Das ist ja das Problem mit dem Anpassen des Filters.
Delphi-Quellcode:
procedure TForm1.Speichern(Sender: TObject);
var Sudoku:TStringList;
begin
Sudoku:=TStringList.create;
SaveDialog1.Filter:='*.sud|*.Sud';
if SaveDialog1.execute
then
  begin
  Sudoku[0]:=Memo1.lines[0];
  Sudoku.SaveToFile(SaveDialog1.FileName);
  end;
Sudoku.Free;
end;


procedure TForm1.Sudokuladen1Click(Sender: TObject);
var Sudoku:TStringList;
begin
Sudoku:=TStringList.create;
OpenDialog1.Filter:='*.sud|*.SUD';
if OpenDialog1.execute
then
  Sudoku.LoadFromFile(OpenDialog1.FileName);
  Memo1.Lines.add(Sudoku[0]);
  end;
Sudoku.Free;
end;
Im OpenDialog kann ich dann nur *.sud als Filter auswählen. Dennoch zeigt er keinerlei Anstalten mir dann die gespeicherte(n) Dateie(n) anzuzeigen. Und über den Explorer mit Rechtsklick>Eigenschaften zeigt er mir als Format nur "Datei" an.
Ich möchte aber, dass er mir im OpenDialog sämtliche *.sud-Dateien anzeigt. Aber irgendwie ignoriert er den Filter beim Speichern.
So funktioniert es auf alle Fälle nicht. :?
Und wenn ich als Filter *.txt eingebe, speichert er das auch im "Datei"-Format. Im Explorer zeigt er es mir aber nicht als WordPad-Datei oder so an. Sowohl .txt als auch .sud kann man mit Rechtsklick>Öffnen>Programm aus Liste auswählen>Wordpad(oder Editor) öffnen.

@Die Muhkuh
Aber wenn er "ausversehen" mal darin rumspielt, verändert er damit die gespeicherten Sudokus. Sind die Sudokus verändert, ist das nicht mehr umkehrbar und der Nutzer müsste sie löschen. Das möchte ich ihm nicht antun :angel:

Alter Mann 24. Feb 2010 16:43

Re: Wie speichere ich einen String am besten?
 
Hi

Eine Möglichkeit die Daten in ein prpitäres Format zu speichern:

Delphi-Quellcode:
procedure SaveToFile(const FileName : String)
var
  Stream : TStream;
begin
  Stream := TFileStream.Create(FileName, fmCreate);
  try
    SaveToStream(Stream);
  finally
    Stream.Free;
  end;
end;

procedure LoadFromFile(const FileName : String)
var
  Stream : TStream;
begin
  Stream := TFileStream.Create(FileName, fmOpen);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;

procedure SaveToStream(Stream : TStream);
var
  Zeile,
  Splate,
  I      : Integer;
begin
  for I := 1 to 81 do
  begin
    Spalte := (I-1) mod 9;
    Zeile := (I-1) div 9;
    Stream.WriteBuffer(StrToInt(StringGrid.Cells[Spalte, Zeile]), SizeOf(Integer));
  end;
end;

procedure LoadFromStream(Stream : TStream);
var
  Zeile,
  Splate,
  I      : Integer;
begin
  for Zeile := 0 to 8 do
   for Spalte := 0 to 8 do
   begin
    Stream.ReadBuffer(I), SizeOf(Integer));
   StringGrid.Cells[Spalte, Zeile] := IntToStr(I);
   end;
end;
Nicht getestet!!!

Zitat:

Ich möchte aber, dass er mir im OpenDialog sämtliche *.sud-Dateien anzeigt
Ist Multiselect in den Dialogeigenschaften aktiv?

Damit der Explorer eine '*.sud' als Sudoko-Datei idenifiziert must du die Dateiendung registrieren,
siehe hier.

Viele Grüße


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:49 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz