Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Record laden (https://www.delphipraxis.net/89075-record-laden.html)

grader 26. Mär 2007 14:05

Re: Record laden
 
Hallo!

Danke euch erstmal für eure Hilfe! Jetzt sieht es so aus:

Delphi-Quellcode:
procedure TForm1.saverec;
var
  Stream: TStream;
  I: integer;
  Len: Longint;
begin
Stream := TFileStream.Create('c:\TMData.dat', fmCreate);
try
Len := Length(T);
Stream.Write(Len, SizeOf(Len));
for I := 0 to Length(T) - 1 do
begin
Len := Length(IntToStr(T[I].T));
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].T), Len);
Len := Length(IntToStr(T[I].M));
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].M), Len);
Len := Length(IntToStr(T[I].J));
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].J), Len);
Len := Length(T[I].Zh);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].Zh), Len);
Len := Length(T[I].Zm);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].Zm), Len);
Len := Length(T[I].B);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].B), Len);
Len := Length(T[I].T1);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].T1), Len);
Len := Length(T[I].T2);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].T2), Len);
Len := Length(T[I].T3);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].T3), Len);
Len := Length(T[I].T4);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].T4), Len);
Len := Length(T[I].P);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].P), Len);
Len := Length(T[I].N);
Stream.Write(Len, SizeOf(Len));
Stream.Write(PChar(T[I].N), Len);
end;
finally
Stream.Free;
end;
end;
und


Delphi-Quellcode:
procedure TForm1.loadrec;
var
  Stream: TStream;
  I: integer;
  Len: LongInt;
begin
  Stream := TFileStream.Create('c:\TMData.dat', fmOpenRead);
  try
  Stream.Read(Len, SizeOf(Len));
  SetLength(T, Len);
for I := 0 to Len - 1 do
begin
{Stream.Read(Len, SizeOf(Len));
SetLength(T[I].T, Len);
Stream.Read(PChar(T[I].T), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].M, Len);
Stream.Read(PChar(T[I].M), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].J, Len);
Stream.Read(PChar(T[I].J), Len);}
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].Zh, Len);
Stream.Read(PChar(T[I].Zh), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].Zm, Len);
Stream.Read(PChar(T[I].Zm), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].B, Len);
Stream.Read(PChar(T[I].B), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].T1, Len);
Stream.Read(PChar(T[I].T1), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].T2, Len);
Stream.Read(PChar(T[I].T2), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].T3, Len);
Stream.Read(PChar(T[I].T3), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].T4, Len);
Stream.Read(PChar(T[I].T4), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].P, Len);
Stream.Read(PChar(T[I].P), Len);
Stream.Read(Len, SizeOf(Len));
SetLength(T[I].N, Len);
Stream.Read(PChar(T[I].N), Len);
end;
  finally
    Stream.Free;
  end;
end;
Jetzt markiert er folgendes rot und sagt "variable required":

Delphi-Quellcode:
Stream.Write(PChar(T[I].T), Len);
Dieses Tut habe ich übrigens verwendet..
Und da steht das mit dem "^" drin und so geht es auch zu kompilieren geht nur net :gruebel:

Gruß
Stefan

Edit:

hab jetzt noch das hier gefunden, was ich vielleicht später mal probieren werde:

klick

Jetzt hab ich aber erstmal andere Sorgen, morgen letzte Kursarbeit in Physik :roll:

himitsu 26. Mär 2007 14:50

Re: Record laden
 
Dann halt so?
Delphi-Quellcode:
Stream.Write(T[I].B[1], Len);
Aber wie schon mehrmals gefragt ... wie sieht denn die Definition deines Records aus?

grader 26. Mär 2007 15:00

Re: Record laden
 
Delphi-Quellcode:
type
  TDatum = record
  T,M,J: word;
  Zh,Zm,B,O,T1,T2,T3,T4,P,N: String;
end;
und

Delphi-Quellcode:
var
  T: array of TDatum;
Achso wenn ich das aus deinem letzten Post nehme, sagt er nur Array type required! Außerdem verstehe ich nicht ganz was das bewirken soll :gruebel:

himitsu 26. Mär 2007 15:38

Re: Record laden
 
müßte stimmen
Delphi-Quellcode:
// Schreiben
Len := Length(T);
Stream.Write(Len, SizeOf(Len));
for I := 0 to Length(T) - 1 do
begin
  Stream.Write(T[I].T, SizeOf(Word) * 3); // .T, .M und .J zusammen
  Len := Length(T[I].Zh);
    Stream.Write(Len, SizeOf(Len));
    If Len > 0 Then Stream.Write(T[I].Zh[1], Len);
  Len := Length(T[I].Zm);
    Stream.Write(Len, SizeOf(Len));
    If Len > 0 Then Stream.Write(T[I].Zm[1], Len);
  Len := Length(T[I].B);
    Stream.Write(Len, SizeOf(Len));
    If Len > 0 Then Stream.Write(T[I].B[1], Len);
  ...
  Len := Length(T[I].N);
    Stream.Write(Len, SizeOf(Len));
    If Len > 0 Then Stream.Write(T[I].N[1], Len);
end;


// Lesen
Stream.Read(Len, SizeOf(Len));
SetLength(T, Len);
for I := 0 to Length(T) - 1 do
begin
  Stream.Read(T[I].T, SizeOf(Word) * 3); // .T, .M und .J zusammen
  Stream.Read(Len, SizeOf(Len));
    SetLength(T[I].Zh, Len);
    If Len > 0 Then Stream.Read(T[I].Zh[1], Len);
  ...
  Stream.Read(Len, SizeOf(Len));
    SetLength(T[I].N, Len);
    If Len > 0 Then Stream.Read(T[I].N[1], Len);
end;
Stream.Read/Write wollen ja einen Var/Const-Parameter, welcher auf den Stringinhalt zeigt und dieser beginnt beim 1. Zeichen.


Anders gesagt ... die Implementation von Stream.Read/Write ist sch*** :angel2:


Ach ja, da der Zugriff auf [1] nicht möglich ist, wenn der String leer ist, muß halt nich mit IF dieser Zustand abgefangen werden.
Wenn du garantieren kannst, daß die strings immer mit mindestens einem Zeichen gefüllt sind, dann kannst du natürlich die IF-Abfragen weglassen und direkt Schreiben/Lesen.

grader 26. Mär 2007 15:42

Re: Record laden
 
Du warst schneller, werds gleich mal probieren!

Chemiker 26. Mär 2007 16:07

Re: Record laden
 
Hallo grader,

schau dir mal das Tut. ‚Records in einem FileStream speichern’ an. Ich würde nicht lange Strings verwenden, sondern kurze Strings, wenn das Möglich ist. Bei langen String muss immer die Länge der Strings mit verwaltet werden, dies ist sehr aufwendig.
Bei kurzen Strings ist der Record immmer gleich groß.

statt:
Delphi-Quellcode:
type
  TDatum = record
  T,M,J: word;
  Zh,Zm,B,O,T1,T2,T3,T4,P,N: String;
end;
Delphi-Quellcode:
const strLaenge= 20; // Strings sind 20 Zeichen lang.
type
 TDatum = packed record
    T: Word;
    M: Word;
    J: Word;
    Zh: string[strLaenge];
    Zm: string[strLaenge];
    B: string[strLaenge];
    O: string[strLaenge];
    T1: string[strLaenge];
    T2: string[strLaenge];
    T3: string[strLaenge];
    T4: string[strLaenge];
    P: string[strLaenge];
    N: string[strLaenge];
 end;

Bis bald Chemiker

grader 26. Mär 2007 16:12

Re: Record laden
 
Boah habs jetzt probiert und Ernüchterung folgte zugleich.. Ging wieder nicht :wall:

Hab aber auch rausgefunden warum:

Delphi-Quellcode:
for I := 0 to Length(T) - 1 do
Hab Length(T) testweise durch eine Zahl ersetzt und voila es funktioniert! Dann hab ich mir Length(T) mal ausgeben lassen und egal wie viele Einträge vorhanden sind er gibt immer nur "1" aus! Es nimmt halt kein Ende, aber ich glaube jetzt isses nicht mehr weit ;)

@Chemiker

Ja das hatte ich auch schon mal gelesen, aber irgendwie hatte ich dann an anderen Stellen Probleme mit den ShortStrings zu arbeiten.. Is aber auch schon ein Stück her, werds dann nochmal probieren, THX :)

himitsu 26. Mär 2007 16:40

Re: Record laden
 
Stream.Read/.Write sind doch bei dir so definiert?
Delphi-Quellcode:
Read(var Buffer; Count: Longint): Longint;
Write(const Buffer; Count: Longint): Longint;
Also dann sollte es doch funktionieren? :gruebel:

Hast du mal ein Testprogramm zur Verfügung?




Jedenfalls zu Chemiker's Vorschlag:
strLaenge = maximale StringLänge (mehr geht dann nicht rein und soviel wird auch immer gespeichert, selbt wenn weniger drin ist)
Delphi-Quellcode:
// Schreiben
Len := Length(T);
Stream.Write(Len, SizeOf(Len));
for i := 0 to Length(T) - 1 do
  Stream.Write(T[i], SizeOf(TDatum));

// Lesen
Stream.Read(Len, SizeOf(Len));
SetLength(T, Len);
for i := 0 to Length(T) - 1 do
  Stream.Read(T[i], SizeOf(TDatum));
Bei 'nen packed Array (ebenfalls mit ShortStrings) müßte es auch so gehn:
Delphi-Quellcode:
// Schreiben
Len := Length(T);
Stream.Write(Len, SizeOf(Len));
Stream.Write(T[0], SizeOf(TDatum) * Length(T));

// Lesen
Stream.Read(Len, SizeOf(Len));
SetLength(T, Len);
Stream.Read(T[0], SizeOf(TDatum) * Length(T));

grader 26. Mär 2007 16:57

Re: Record laden
 
Liste der Anhänge anzeigen (Anzahl: 1)
ööhm ich glaube nicht aber ich weiß auch grad net wie und wo :angel2:

Hab dir mein Prog mal in den Anhang geladen, aber ohne die .EXE..

Und bitte nicht wundern, da sind 6 Units, aber ich benutze nur eine, wenn ich die anderen aber lösche gehts net mehr..

Chemiker 26. Mär 2007 17:33

Re: Record laden
 
Hallo grader,

Zitat:

Zitat von himitsu
strLaenge = maximale StringLänge (mehr geht dann nicht rein und soviel wird auch immer gespeichert, selbt wenn weniger drin ist)

Das sollte aber bei den heutigen Festplatten keine Problem sein.


Vieleicht hilft dir das weiter:

Delphi-Quellcode:
unit FileStreamHilfeUnit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Edit7: TEdit;
    Edit8: TEdit;
    Edit9: TEdit;
    Edit10: TEdit;
    Edit11: TEdit;
    Edit12: TEdit;
    Edit13: TEdit;
    Edit14: TEdit;
    Edit15: TEdit;
    Edit16: TEdit;
    Edit17: TEdit;
    Edit18: TEdit;
    Edit19: TEdit;
    Edit20: TEdit;
    Edit21: TEdit;
    Edit22: TEdit;
    Edit23: TEdit;
    Edit24: TEdit;
    Edit25: TEdit;
    Edit26: TEdit;
    Button1: TButton;
    Button2: TButton;
    DatenSatzNr: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

const strLaenge= 20; // Strings sind 20 Zeichen lang.
type
TDatum = packed record
    T: Word;
    M: Word;
    J: Word;
    Zh: string[strLaenge];
    Zm: string[strLaenge];
    B: string[strLaenge];
    O: string[strLaenge];
    T1: string[strLaenge];
    T2: string[strLaenge];
    T3: string[strLaenge];
    T4: string[strLaenge];
    P: string[strLaenge];
    N: string[strLaenge];
end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function Stream_MW_Rec_Anhaengen
                           (f: TFileStream; MWRec: TDatum): boolean;
begin
  try
    f.Position:=0;
    f.Seek(0, soFromEnd);   // Datenzeiger auf das Ende des Streams setzen.
    f.WriteBuffer(MWRec, SizeOf(TDatum));
    result:= TRUE;
  except
    ShowMessage('Es ist beim Datensatz speichern ein Fehler aufgetreten!');
    result:= FALSE;
  end;
end;
function Stream_MW_Rec_Lesen (f: TFileStream; var MWRec: TDatum;
                              DatensatzNr: integer): boolean;
begin
  try
    f.Position:=0;
    // An dieser Stelle wird der Datei-Zeiger auf den zu lesenden
    // Datensatz gestellt. Durch -soFromBeginning- wird der Dateizeiger
    // auf den Anfang gesellt.
    f.Seek((SizeOf(TDatum)*DatensatzNr), soFromBeginning);
    f.ReadBuffer(MWRec, SizeOf(TDatum));
    result:= TRUE;
  except
    ShowMessage('Es ist beim Datensatz lesen ein Fehler aufgetreten!');
    result:= FALSE;
  end;
end;

function Stream_MW_Rec_DatenSatzAnzahl
                   (f: TFileStream; MWRec: TDatum): integer;
begin
  result:= 0;
  if f.Size>0 then
  begin
    // Berechnung: Gesamte Stream-Lämge / TMW_Stream_Rec
    // Das ergibt die Datensatz-Anzahl
    result:= trunc(f.Size/SizeOf(TDatum));
  end;
end;

function Stream_oeffnen (var f: TFileStream ;const DateiName: string): boolean;
begin
  result:= TRUE;
  try
    {-- FileStream zum Lesen u. Schreiben uneingeschränkt öffnen   -----------} 
    f:= TFileStream.Create(DateiName, fmOpenReadWrite or fmShareDenyNone)
  except
    try
     { FileStream neu anlegen, tritt hier ein Fehler auf so wird das Prg. ab-  } 
     { gebrochen und zur der aufrufende Routine zurückgesprungen.             } 
     f:= TFileStream.Create(DateiName, fmCreate or fmShareDenyNone);
    except
      ShowMessage('Fehler beim Erzeugen der Datei:'+#13+DateiName);
      Exit; // Zur aufrufenden Routine zurück.
    end;
    result:= FALSE;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var f: TFileStream;
    TDatum_Rec: TDatum;
begin
  with TDatum_Rec do
  begin
    T:= strtoint(Edit1.Text);
    M:= strtoint(Edit2.Text);
    J:= strtoint(Edit3.Text);
    Zh:= Edit4.Text;
    Zm:= Edit5.Text;
    B:= Edit6.Text;
    O:= Edit7.Text;
    T1:= Edit8.Text;
    T2:= Edit8.Text;
    T3:= Edit9.Text;
    T4:= Edit10.Text;
    P:= Edit11.Text;
    N:= Edit12.Text;
  end;
  Stream_oeffnen (f ,'f:\TMData.dat');
  Stream_MW_Rec_Anhaengen (f, TDatum_Rec);
  f.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var f: TFileStream;
    TDatum_Rec: TDatum;
begin
  Stream_oeffnen (f ,'c:\TMData.dat');
  Stream_MW_Rec_Lesen (f, TDatum_Rec, strtoint(DatensatzNr.Text)-1);
  with TDatum_Rec do
  begin
    Edit14.Text:= inttostr(T);
    Edit15.Text:= inttostr(M);
    Edit16.Text:= inttostr(J);
    Edit17.Text:=Zh;
    Edit18.Text:=Zm;
    Edit19.Text:=B;
    Edit19.Text:=O;
    Edit20.Text:=T1;
    Edit21.Text:=T2;
    Edit22.Text:=T3;
    Edit23.Text:=T4;
    Edit24.Text:=P;
    Edit25.Text:=N;
  end;
end;

end.


Bis bald Chemiker


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:56 Uhr.
Seite 2 von 3     12 3      

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