Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi File of eigener Typ (https://www.delphipraxis.net/151619-file-eigener-typ.html)

Chemiker 26. Mai 2010 06:56

Re: File of eigener Typ
 
Hallo eragon123,

für die Deklaration des Records sollte man, wenn man in speichert mit packed arbeiten. In Deinen Beispiel würde man 7Byte pro Datensatz sparen.

Also der Record sollte so aussehen:

Delphi-Quellcode:
buch = packed record
  Titel: string[50];
  Autor: string[50];
  Erscheinungsjahr: TDate;
  DatumEintrag: TDate;
  ISBN: Integer;
  Bewertung: TNote;
  Kommentar: string[100];
  Privat: Boolean;
end;
Zudem ist eine Fehlerbehandlung bei I/O-Operationen auch nicht verkehrt(eigentlich zwingend notwendig).

Bis bald Chemiker

himitsu 26. Mai 2010 08:21

Re: File of eigener Typ
 
Zitat:

Zitat von Chemiker
für die Deklaration des Records sollte man, wenn man in speichert mit packed arbeiten.

Sowas sollte man eh immer machen, sobald Daten übertragen oder gespeichert werden sollen,
also sobald Daten den Prozess/die Programminstanz, das Modul (EXE/DLL) verlassen.

Ebenso sollte man nur statische Typen nehmen.

z.B. Integer und Char können sich ja schnell mal in der nächsten Delphi-/Compilerversion verändern
(ein gutes Beispiel sind die vielen Unicode-Probleme mit alten Programmen/Codes, seit Delphi 2009)

Zitat:

Zitat von Chemiker
In Deinen Beispiel würde man 7Byte pro Datensatz sparen.

Aber dennoch würde ich eine "ordentliche" Speicherausrichtung nicht übergehen und hierbei manuell für die

Delphi-Quellcode:
TNote = 1..6;
TBuch = packed record                            8 Byte-Align   4 Byte
  Titel: String[51];              //  52 Byte = 6,5  > 6,5   = 13   >13
  Autor: String[51];              //  52 Byte = 6,5  >13     = 13   >26
  Erscheinungsjahr: TDate;        //   8 Byte = 1    >14     = 2   >28
  DatumEintrag: TDate;            //   8 Byte = 1    >15     = 2   >30
  ISBN: LongInt;                  //   4 Byte = 0,5  >15,5   = 1   >31
  Kommentar: String[105{oder 97}]; // 106 Byte = 13,25 >28,75  = 26,5 >57,5
  Bewertung: TNote;               //   1 Byte = 0,125>28,875 = 0,25>57,75
  Privat: Boolean;                //   1 Byte = 0,125>29     = 0,25>58
end;
Für 'nen 32-Bit-Prozess also eine passende Ausrichtung.

Progman 26. Mai 2010 08:31

Re: File of eigener Typ
 
Hier mal eine effektivere Variante zum Einlesen:
Delphi-Quellcode:
procedure LoadArray; // Datei öffnen
var
  i, anzahl: Integer;
  f: TFileStream;
begin
  if FileExists(Path+OpenName) then begin //Path und OpenName sind Verzeichnis und Dateiname
    try
      f := TFileStream.Create(Path+OpenName, fmOpenRead)
    except
      ShowMessage('Die Datei konnte nicht geöffnet werden!');
      Exit;
    end;
    f.ReadBuffer(Anzahl, SizeOf(Integer)); //anzahl wird hier mit der Anzahl der Records geladen
    SetLength(MeinArray, Anzahl); //und kann direkt für SetLenghth genutzt werden
    for i := 0 to Anzahl-1 do f.ReadBuffer(MeinArray[i],SizeOf(TMeinRec)); // alle Records einlesen
    f.Free;
  end;
end;
Array und Record müssen natürlich angepasst werden. Ich hab das mal eben aus einer Anwendung von mir rauskopiert :-)

himitsu 26. Mai 2010 08:43

Re: File of eigener Typ
 
effktiver =
Delphi-Quellcode:
f.ReadBuffer(MeinArray[0],SizeOf(TMeinRec) * Anzahl); // alle Records einlesen
noch was zur Fehlerbehandlung:
- TFileStream.Create gibt schon eine gute Fehlermeldung aus ... diese muß ja nicht unbedingt zerstören
- und was passiert mit "f", wenn ReadBuffer oder SetLength eine Exception werfen?
Delphi-Quellcode:
if FileExists(Path+OpenName) then begin //Path und OpenName sind Verzeichnis und Dateiname
  f := TFileStream.Create(Path+OpenName, fmOpenRead)
  try
    f.ReadBuffer(Anzahl, SizeOf(Integer)); //anzahl wird hier mit der Anzahl der Records geladen
    SetLength(MeinArray, Anzahl); //und kann direkt für SetLenghth genutzt werden
    f.ReadBuffer(MeinArray[0],SizeOf(TMeinRec) * Anzahl); // alle Records einlesen
  finally
    f.Free;
  end;
end
else
  raise Exception.CreateFmt('Datei "%s" existiert nicht.', [OpenName]);
oder
Delphi-Quellcode:
if FileExists(Path+OpenName) then begin //Path und OpenName sind Verzeichnis und Dateiname
  f := TFileStream.Create(Path+OpenName, fmOpenRead)
  try
    Anzahl := f.Size div SizeOf(TMeinRec); // Anzahl wird aus der Dateigröße berechnet
    SetLength(MeinArray, Anzahl); //und kann direkt für SetLenghth genutzt werden
    f.ReadBuffer(MeinArray[0], SizeOf(TMeinRec) * Anzahl); // alle Records einlesen
  finally
    f.Free;
  end;
end
else
  raise Exception.CreateFmt('Datei "%s" existiert nicht.', [OpenName]);

Progman 26. Mai 2010 08:54

Re: File of eigener Typ
 
Das war auch nur ganz flüchtig rauskopiert.
Mir ging es eigentlich nur darum, dieses (sehr uneffektive) schrittweise SetLength zu eliminieren :-)

Chemiker 26. Mai 2010 22:09

Re: File of eigener Typ
 
Hallo himitzu,

Zitat:

Zitat von himitzu
Aber dennoch würde ich eine "ordentliche" Speicherausrichtung nicht übergehen und hierbei manuell für die

Delphi-Quellcode:
TNote = 1..6;
TBuch = packed record                            8 Byte-Align   4 Byte
  Titel: String[51];              //  52 Byte = 6,5  > 6,5   = 13   >13
  Autor: String[51];              //  52 Byte = 6,5  >13     = 13   >26
  Erscheinungsjahr: TDate;        //   8 Byte = 1    >14     = 2   >28
  DatumEintrag: TDate;            //   8 Byte = 1    >15     = 2   >30
  ISBN: LongInt;                  //   4 Byte = 0,5  >15,5   = 1   >31
  Kommentar: String[105{oder 97}]; // 106 Byte = 13,25 >28,75  = 26,5 >57,5
  Bewertung: TNote;               //   1 Byte = 0,125>28,875 = 0,25>57,75
  Privat: Boolean;                //   1 Byte = 0,125>29     = 0,25>58
end;
Für 'nen 32-Bit-Prozess also eine passende Ausrichtung.

damit ist der Record doch genauso groß wie der vom Beitragsersteller ohne packed.
Zudem ist man teilweise an die Größe von Feldern gebunden. Für eine deutsche PLZ braucht man nicht mehr als 5 Stellen(es sei denn wir kaufen demnächst Griechenland und Spanien usw.).

Bis bald Chemiker

himitsu 26. Mai 2010 22:14

Re: File of eigener Typ
 
Man kann die Werte ja nach unten runden (bei 32 Bit reicht es ja auch, wenn man auf 4 Byte ausrichtet)

Füllfelder und eine andere Anorfnung der Felder machen schon viel aus, aber nja
Hauptsache ist ja, daß man bei sowas Packed und feste Typen verwendet und der Rest ist Optimierungssache, welche man notfalls auch mal weglassen kann wenn es einem nicht so wichtig ist. :stupid:


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:33 Uhr.
Seite 2 von 2     12   

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