Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Record und in File speichern (https://www.delphipraxis.net/80928-record-und-file-speichern.html)

delphinia 17. Nov 2006 15:17


Record und in File speichern
 
hey,

habe folgenden Record:

Delphi-Quellcode:
type
  TArtRec = record
    ID: Integer;
    D1: string;
    D2: string;
  end;
var
  ArtArr: array of TArtRec;

Wie speichere ich dessen Inhalt am sinnigstenn in einer File?

Der_Unwissende 17. Nov 2006 15:31

Re: Record und in File speichern
 
Hi,
so richtig elegant geht das leider nicht.
Du hast die Auswahl dir eine eigene Dateistruktur zu überlegen und die zu implementieren, kannst aber auch auf ein Ini-File, XML oder CSV zurückgreifen. Zu letzten findest du eine Menge Komponenten, teilweise auch gleich bei Delphi beiliegend.
Legst du dir ein eigenes Dateiformat an, so solltest du darauf achten, dass du die Länge der Strings speichern musst. Ein String hat in Delphi eine Variable Länge von bis zu 2^{31}-1 Zeichen (sind ca. 2.1 Mrd. Zeichen). Da ein Record eine feste größe hat, musst du hier aufpassen, Strings werden nur als Zeiger im Record abgelegt. Möchtest du den Inhalt in ein Stream schreiben, musst du den Strings dereferenzieren (z.B. D1[1], wäre jetzt das erste Zeichen im String und ist damit der Anfang). Dabei geht dann aber dass davor sitzende Längenwort verloren, deswegen wie gesagt, musst du die Länge vorher abspeichern.

Gruß Der Unwissende

RavenIV 17. Nov 2006 15:41

Re: Record und in File speichern
 
als Schritt Nr.1 solltest Du die String durch string[xxx] ersetzen.
Delphi-Quellcode:
type
  TArtRec = record
    ID: Integer;
    D1: string[100];
    D2: string[100];
  end;
Dann kannst Du folgendermassen abspeichern:
Delphi-Quellcode:
procedure Speichern ();
var
  stream           : TFileStream;
  filename         : string;
begin
  filename := ChangeFileExt (Application.ExeName, '.ext'); // Filename setzen
  stream := TFileStream.Create (filename, fmCreate); // Stream erzeugen
  try
    stream.WriteBuffer (PDeinRecord^, SizeOf (DeinRecord));
  finally
    stream.Free; // Stream wieder freigeben
  end;
end;
Natürlich kannst Du auch das ganze Array speichern, indem Du eine geeignete Schleife um das Speichern herum legst.

delphinia 17. Nov 2006 16:16

Re: Record und in File speichern
 
Ok ich ahb es so gelöst!

ist da was zu verbessern drinne?


Delphi-Quellcode:
function TWK_Form.write_Data: boolean;
var
  f: Textfile;
  i: Integer;
begin
  pro_1.MaxValue := allcnt;
  Result := False;

  AssignFile(f, FileName);
  try
    if FileExists(FileName) = False then
      Rewrite(f)
    else
    begin
      ReWrite(f);
    end;

    for i := 0 to allcnt - 1 do
    begin
      pro_1.Progress := i;
      WriteLn(f, IntToStr(ArtArr[i].ID) + ';' + ArtArr[i].d1 + ';' + ArtArr[i].d2);
      Application.ProcessMessages;
    end;

    Result := True;
  finally
    CloseFile(f);
    pro_1.Progress := 0;
  end;
end;

Luckie 17. Nov 2006 16:18

Re: Record und in File speichern
 
Ich würde nicht mit Records arbeiten, sondern mit Klassen: http://www.delphipraxis.net/internal...=640273#640273

Und zuim Speichern würde ich eine XML-Datei nehmen.

peteress 17. Nov 2006 18:20

Re: Record und in File speichern
 
Geht man von Pascal in der ursprünglichen Version aus, dann ist die obige Deklaration gleichbedeutend mit:
Delphi-Quellcode:
  TArtRec = record
    ID: Integer;
    D1: string[255];
    D2: string[255];
  end;
Dann geht mdas mit dem Speichern schon sehr elegant:
Delphi-Quellcode:
var i :integer;
  aFile: File of TArtRec;
begin
  AssignFile(aFile,'Filename');
  Rewrite(aFile);
  for i := 0 to length(ArtArr)-1 do begin;
    Write(aFile, ArtArr[i]);
  end;
  CloseFile(aFile);
end;
Gruss
Peter

delphinia 18. Nov 2006 13:43

Re: Record und in File speichern
 
hmm na ja wichtig ist das die ; mit in der speicehrung zwecks CSV verwertbarkeit vorhanden sind!

peteress 19. Nov 2006 11:51

Re: Record und in File speichern
 
Zitat:

Zitat von delphinia
hmm na ja wichtig ist das die ; mit in der speicehrung zwecks CSV verwertbarkeit vorhanden sind!

Nun, das ist eine Information, die du sinnigerweise von Anfang an hättest mit uns teilen sollen.
Dann iterier durch das Array, schreibe jedes Record in eine Zeile einer TStringlist, trenne die Einträge durch Komma, und nutze dann die Methode TStringlist.SavetoFile zum speichern

cu
Peter

Nicodius 28. Feb 2007 15:39

Re: Record und in File speichern
 
ich hab dasselbe problem

Delphi-Quellcode:
  Vert_Ent = record
  vtjahr : Integer;
  vtproz : array [0..11] of Integer;
end;

Steuer = record
  st_bez : string[30];
  st_jahr : array [0..11] of Integer;
  st_vert : string[10];
  st_aufk : array [0..11] of longint;
end;

Modell = record
  und_bez : string[30];
  und_st : array [0..31] of Steuer;
end;


Alles= record
  Vert_ast : array [0..30] of array [0..22] of string ;
  vert_datum : array [0..31] of Vert_ent;
  mod_ : array [0..15] of Modell;


procedure TMain.Speichern1Click(Sender: TObject);
var
  stream           : TFileStream;
  filename         : string;
begin
  filename := ChangeFileExt (Application.ExeName, '.ext'); // Filename setzen
  stream := TFileStream.Create (filename, fmCreate); // Stream erzeugen
  try
    stream.WriteBuffer (TAlles^, SizeOf (TAlles)); // hier kommt eine fehelrmeldung dass nach TAlles^ eine klammer fehlt (  und
                                                    // dass eine anweisung erforderlich ist aber ein integer gefunden wurde
  finally
    stream.Free; // Stream wieder freigeben
  end;
end;
was mach ich falsch?

lg nico

Der_Unwissende 28. Feb 2007 15:47

Re: Record und in File speichern
 
Zitat:

Zitat von Nicodius
ich hab dasselbe problem
Delphi-Quellcode:
Alles= record
  Vert_ast : array [0..30] of array [0..22] of string ;

Hi,
das sollte schon nicht funktionieren. Ein String hat keine feste Größe, die wird aber von einem Record benötigt. Ein String kann im Worst-Case 2^31 Zeichen enthalten, das wären gute 2 GByte pro String, bei 31 * 23 * 2 GByte dürfte das doch etwas viel werden (pro Record!).

Zitat:

Zitat von Nicodius
ich hab dasselbe problem
Delphi-Quellcode:
procedure TMain.Speichern1Click(Sender: TObject);
var
  stream           : TFileStream;
  filename         : string;
begin
  filename := ChangeFileExt (Application.ExeName, '.ext'); // Filename setzen
  stream := TFileStream.Create (filename, fmCreate); // Stream erzeugen
  try
    stream.WriteBuffer (TAlles^, SizeOf (TAlles)); // hier kommt eine fehelrmeldung dass nach TAlles^ eine klammer fehlt (  und
                                                    // dass eine anweisung erforderlich ist aber ein integer gefunden wurde
  finally
    stream.Free; // Stream wieder freigeben
  end;
end;
was mach ich falsch?

Wo kommt denn TAlles her? Ist TAlles ein Datentyp? Dann würde das mit der Klammer daher kommen, dass Du schon eine Variable brauchst, die Du hier übergibst. TAlles(x) wäre dann der Cast der Variable x in ein TAlles. Jedenfalls brauchst Du eine Variable vom Typ TAlles, die kannst Du dann übergeben, sizeOf(Talles) kann dann hingegen bleiben (solange es sich nicht um einen Zeiger handelt, der sollte dann aber auch besser PAlles heißen!)

Gruß Der Unwissende

Nicodius 1. Mär 2007 20:34

Re: Record und in File speichern
 
danke dir

das mit TAlles war nur oben ein tippfehler - aber das war nicht das problem (hatte in der zwischenablage die erste version das hab ich dann aber selber korrigiert)

ich werds mal ausprobieren

vielen dank

nico

Nicodius 11. Mär 2007 13:07

Re: Record und in File speichern
 
die fehlermeldungen sind noch immer die gleichen ich kenn mich gar nicht mehr aus :(


Delphi-Quellcode:
Steuer = record
  st_bez : string[30];
  st_jahr : array [0..11] of Integer;
  st_vert : string[10];
  st_aufk : array [0..11] of longint;
end;

Modell = record
  und_bez : string[30];
  und_st : array [0..31] of Steuer;
end;


Alles= record
  Vert_ast : array [0..30] of array [0..22] of string ;
  vert_datum : array [0..31] of Vert_ent;
  mod_ : array [0..15] of Modell; // mod ist ein reserviertes wort! modular - rest ..
end;

.
.
.

procedure TMain.Speichern1Click(Sender: TObject);
var
  stream           : TFileStream;
  filename         : string;
begin
  filename := ChangeFileExt (Application.ExeName, '.ext'); // Filename setzen
  stream := TFileStream.Create (filename, fmCreate); // Stream erzeugen
  try
    stream.WriteBuffer (Alles, SizeOf (Alles));
  finally
    stream.Free; // Stream wieder freigeben
  end;
end;

end.

Hawkeye219 11. Mär 2007 13:31

Re: Record und in File speichern
 
Hallo Nico,

eigentlich hat Der_Unwissende in Beitrag #10 alles erklärt. Die Methode Delphi-Referenz durchsuchenTStream.WriteBuffer erwartet als ersten Parameter eine Variable, du übergibst einen Datentyp. Aber selbst mit einer Variablen wird es in deinem Fall nicht funktionieren, da der Typ Alles dynamische Elemente (string) enthält, die nicht direkt in einen Stream geschrieben werden können. Mögliche Lösungen wurden in den vorigen Beiträgen dieses Threads aufgezeigt.

Gruß Hawkeye

Nicodius 11. Mär 2007 13:51

Re: Record und in File speichern
 
ja ungefähr weiß ich jetzt wies geht das stimmt aber ich schaffs nicht das umzusetzen

Delphi-Quellcode:
Steuer = record
  st_bez : string[30];
  st_jahr : array [0..11] of Integer;
  st_vert : string[10];
  st_aufk : array [0..11] of longint;
end;

Modell = record
  und_bez : string[30];
  und_st : array [0..31] of Steuer;
end;


Alles= record
  Vert_ast : array [0..30] of array [0..22] of string ;
  vert_datum : array [0..31] of Vert_ent;
  mod_ : array [0..15] of Modell; // mod ist ein reserviertes wort! modular - rest ..
end;

ich will doch nur dieses alles record speichern und laden können das dürfte doch nicht alzu kompliziert sein(ich hab vorher nie mit assign etc gearbeitet ich orientier mich da ganz an der delphihilfe)

wenn das alles gespeichert und geladen werden kann hab ich das schwierigste gescahfft bei dem programm


lg nico

Hawkeye219 11. Mär 2007 14:13

Re: Record und in File speichern
 
Ok, der von Luckie vorgeschlagene Weg über Klassen ist sicher der beste, für den Anfang aber vielleicht etwas zu steinig. Ändere zunächst die Definition von Alles wie folgt ab:

Delphi-Quellcode:
Alles= record
//  Vert_ast : array [0..30] of array [0..22] of string;
  Vert_ast : array [0..30] of array [0..22] of string[255]; // <-- hier geändert
  vert_datum : array [0..31] of Vert_ent;
  mod_ : array [0..15] of Modell;
end;
So erreichen wir, daß Delphi einen ShortString mit einer festen Länge verwendet, der direkt in einem Stream gespeichert werden kann. Nun benötigen wir noch eine Variable, welche die zu speichernden Daten aufnimmt:

Delphi-Quellcode:
var
  AlleDaten : Alles;
In dieser Variablen legst du alle zu speichernden Daten ab. Die Methode Speichern1Click muß nur an einer Stelle geändert werden:

Delphi-Quellcode:
// stream.WriteBuffer (Alles, SizeOf (Alles));
stream.WriteBuffer (AlleDaten, SizeOf (AlleDaten)); // <-- hier geändert
Nun sollte das Speichern funktionieren. Beim Laden der Daten ist es ähnlich. Mit ReadBuffer liest du die Daten in die Variable AlleDaten ein, anschließend kannst du sie verarbeiten.

Wenn dein Programm dann funktioniert, und du die Vorgänge nachvollziehen kannst, solltest du dich mit anderen Möglichkeiten der Datenspeicherung vertraut machen (dynamische Strukturen, Klassen). Der jetzige Weg ist ziemlich unflexibel und wird spätestens bei größeren Datenmengen zu Problemen führen.

Gruß Hawkeye

Nicodius 11. Mär 2007 14:44

Re: Record und in File speichern
 
ok vielen herzlichen dank


problem ist das hier wird ja nur in den zwischenspeicher geschrieben oder?

die datei sollte jederzeit speicher und ladbar sein

bei den daten handelt es sich um modelle zur finanzausgleichsrechnung es wird also nicht eine allzugroße menge an daten zu speichern sein müssen

also zeurst nochmals danke aber mit dieser methode werde ich leider nicht allzu viel anfangen können sofern es tatsächlich nur in den zwischenspeicher "kopiert" wird

lg nico

Nicodius 12. Mär 2007 06:47

Re: Record und in File speichern
 
ich werds jetzt mal über eine stringlist probieren schaun ob ich das schön hinkriege

lg nico

bitsetter 12. Mär 2007 12:23

Re: Record und in File speichern
 
Hallo Nicodius,

Zitat:

Zitat von Nicodius
ok vielen herzlichen dank


problem ist das hier wird ja nur in den zwischenspeicher geschrieben oder?

die datei sollte jederzeit speicher und ladbar sein

lg nico

So lässt sich die Datei doch jederzeit laden und speichern oder?
Du kannst auch mehrere Datensätze mit der Hilfe von arrays mit setLength() anlegen und speichern.

Delphi-Quellcode:
type
Vert_Ent = record
  vtjahr : Integer;
  vtproz : array [0..11] of Integer;
end;

Steuer = record
  st_bez : string[30];
  st_jahr : array [0..11] of Integer;
  st_vert : string[10];
  st_aufk : array [0..11] of longint;
end;

Modell = record
  und_bez : string[30];
  und_st : array [0..31] of Steuer;
end;

Alles= record
//  Vert_ast : array [0..30] of array [0..22] of string;
  Vert_ast : array [0..30] of array [0..22] of string[255]; // <-- hier geändert
  vert_datum : array [0..31] of Vert_ent;
  mod_ : array [0..15] of Modell;
end;

//schreiben
procedure TForm1.Button1Click(Sender: TObject);
var
  AlleDaten : Alles;
  stream : TFileStream;
  filename : string;
begin
  filename := ChangeFileExt (Application.ExeName, '.ext');
  stream := TFileStream.Create (filename, fmCreate);
  AlleDaten.mod_[2].und_bez:= 'Haus';//Beispiel
  try
    stream.WriteBuffer(AlleDaten, SizeOf (AlleDaten));
  finally
    stream.Free;
  end;
end;

//lesen
procedure TForm1.Button2Click(Sender: TObject);
var
  AlleDaten : Alles;
  stream : TFileStream;
  filename : string;
begin
  filename := ChangeFileExt(Application.ExeName, '.ext');
  if FileExists(filename) then
  begin
    stream := TFileStream.Create (filename, fmOpenRead);
    try
      stream.ReadBuffer(AlleDaten, SizeOf (AlleDaten));
    finally
      stream.Free;
    end;
    caption:= AlleDaten.mod_[2].und_bez;//Beispiel
  end;
end;

Nicodius 13. Mär 2007 05:54

Re: Record und in File speichern
 
ahhh :D jetzt versteh ichs hab leider zu lange nicht mehr mit records gearbeitet

vielen dank :)

lg Nico


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:27 Uhr.

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