Announcement

Collapse
No announcement yet.

Dyn Array mit Werten aus Datei füllen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dyn Array mit Werten aus Datei füllen

    Hallo,

    ich möchte eine untypisierte Datei in ein dynamisches Array einlesen. Ich bekam nach einiger Zeit immer Speicherprobleme.
    Laut diesen Textes hier http://www.dsdt.info/insider/sprache...hermanager.php
    sollte man in Delphi die Länge des dynamischen Array nicht in einer Schleife, sondern wenn möglich schon vorher setzen.
    Da ich die Dateigröße habe und auch die Größe des Records, sollte das kein Problem sein... dachte ich :lol:
    Aber wie genau ermittle ich die Größe, die das Array haben muss ? Ein SizeOf(f) wird nicht reichen, oder ?

    Hier die Details:


    type
    rMyRecord= record
    TimeStamp : String;
    WerteID : String;
    Wert : String;
    end;

    var DatenArray : array of rMyRecord;
    f : File;


    SetLength(DatenArray,????);

  • #2
    Auch wenns schon ein wenig her ist...

    type rMyRecord= record
    TimeStamp : String;
    WerteID : String;
    Wert : String;
    end;

    Bei diesem record kannst du keine eindeutige Größe ermitteln..
    Liegt daran, dass der Typ String auch dynamisch den Speicher alloziert, jenachdem wie Lang der String eben ist.


    Abhilfe werden dir da nur endliche Strings schaffen.
    Wenn 255 Zeichen ausreichen ausreichen, kann als Typ String[255] oder ShortString angegeben werden.

    type rMyRecord= record
    TimeStamp : String[255];
    WerteID : String[255];
    Wert : String[255];
    end;

    Bei dieser Methode kommt beim Aufruf von SizeOf(rMyRecord) auch die richtige Größe, also 3*255byte raus.

    Reicht das nicht aus, steht entweder die Möglichkeit offen, die Daten im Record als Array [0..x] of Char anzugeben (x => Maximale Länge des Strings) oder das Array beim Setzen der Länge selbst zu Initialisieren.

    type TArrayOfMyRect = Array of rMyRecord;
    const StringLength: LongWord = 1024; // <- Hier beliebige Länge einfügen

    procedure SetLengthMyArray(var myArray : TArrayOfMyRect, newLength : Integer);
    var
    i : Integer;
    begin
    setLength(myArray, newLength)
    for i := 0 to high(MyArray) do
    begin
    setLength(MyArray[i].TimeStamp, StringLength); // Hier werden jetzt alle Strings mit einer festen Länge initialisiert
    setLength(MyArray[i].WerteID, StringLength);
    setLength(MyArray[i].Wert, StringLength);
    end;
    end;

    function GetSizeOfMyRecord : Integer;
    begin
    Result := 3 * StringLength; // Sollten in das Record noch weitere Werte eingefügt werden müssen diese natürlich aufaddiert werden.
    end;

    Jetzt zum eigentlichen

    Wenn die Datei nur das Array enthält kannst du jetzt die Länge folgendermaßen ermitteln...

    procedure GetArrayOfMyRectFromFile(var myArray: TArrayOfMyRect; const Path: String);
    var
    f : File;
    ArrayLength : Integer;
    begin
    if FileExists(Path) then
    begin
    AssignFile(f, Path);
    Reset(f);
    ArrayLength := FileSize(f) div GetSizeOfMyRect;

    // Oder: Bei String[255] und Array[0..x] of Char => ArrayLength := FileSize(f) div sizeOf(rMyRecord);

    // Arraylänge ergibt sich aus Dateigröße durch Größe eines Recordfeldes
    // Das funktioniert aber nur dann, wenn in der Datei ausschließlich das Array steht

    setLength(myArray, ArrayLength);
    BlockRead(f, myArray, FileSize(f)); // BlockRead läd untypisierte Daten.
    end;
    end

    Hab die Methoden jetzt nicht getestet, aber müssten eigentlich stimmen.

    PS: SizeOf() ermittel immer nur die Größe des Datentypes.

    SizeOf(f : file) würd also nicht die Dateigröße wiedergeben, sondern die des Dateihandles. Sprich egal wie groß die Datei ist, es kommt immer der Gleiche Wert raus.
    Z.B. bei SizeOf(String) kommt, egal wie lang der String ist, immer 4 raus, da sich dahinter ein Pointer verbirgt.
    Außer natürlich bei ner 64 Bit Windows Version =)
    Gruß
    Zuletzt editiert von Biergeneral; 18.07.2007, 01:56. Reason: Wurstfinger beim Tippen ;)

    Comment

    Working...
    X