Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.034 Beiträge
 
Delphi 12 Athens
 
#19

Re: kontinuierlichen Messdaten speichern

  Alt 12. Dez 2007, 17:03
@DeddyH:
aber nur wenn du mit einer festen Datenblockgröße arbeitest

wenn man jetzt hier die Zeit nur sporatisch einfügt, dann ist die Blockgröße nicht mehr fest.



Also du kannst
* entwerder vorm Einlesen die Datei durchgehen und zählen
und dann nochmal alles auslesen und behandeln
* einfach bis zum Dateiende (oder einem Fehler) einlesen
* wärend die datei geschrieben wird mitzählen und dieses dann in einem Header (Dateianfang) nachtragen oder einen Fotter (Daeiende) anhängen
vorm einlesen wird dann nur noch der Heder/Fotter gelesen.


Allgemein solltest du bei den kurzen Messabständen die Datei/Datenbank nicht für jeden Messwert neu öffnen.

hier mal 'ne binäre Variante mit Temperatur als Word gespeichert und direkt über die WinAPI (alles andere wie z.B. TFileStream geht im Grunde auch über die WinAPI).
Außerdem in süßen Klassen und es wird nur alle mindestens 60 Sekunden die Zeit mitgespeichert:

Code:
[Word=$FFFF][Double] // Zeit
[Word] // Temperatur
[Word] // Temperatur
...
[Word=$FFFF][Double] // Zeit
[Word] // Temperatur
Delphi-Quellcode:
Uses Windows, SysUtils;

Type TFileSave = Class
    hFile: THandle;
    Time: LongWord;
    Constructor Create; //Override;
    Destructor Destroy; Override;
  Public
    Function Open(Const FileName: String; CreateNew: Boolean = False): Boolean;
    Function Save(Temp: Single): Boolean;
    Function Close: Boolean;
  End;

  TFileLoad = Class
    hFile: THandle;
    Time: TDateTime;
    Constructor Create; //Override;
    Destructor Destroy; Override;
  Public
    Function Open(Const FileName: String): Boolean;
    Function Load(Out Time: TDateTime; Out Temp: Single): Boolean;
    Function Close: Boolean;
  End;

Constructor TFileSave.Create;
  Begin
    Inherited;
    hFile := INVALID_HANDLE_VALUE;
  End;

Destructor TFileSave.Destroy;
  Begin
    CloseHandle(hFile);
    Inherited;
  End;

Function TFileSave.Open(Const FileName: String; CreateNew: Boolean = False): Boolean;
  Var CD: LongWord;

  Begin
    CloseHandle(hFile);
    If CreateNew Then CD := CREATE_ALWAYS Else CD := OPEN_ALWAYS;
    hFile := CreateFile(PChar(FileName), GENERIC_WRITE, FILE_SHARE_READ,
      nil, CD, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
    SetFilePointer(hFile, 0, nil, FILE_END);
    Time := GetTickCount - 60000;
    Result := hFile <> INVALID_HANDLE_VALUE;
  End;

Function TFileSave.Save(Temp: Single): Boolean;
  Var D: TDateTime;
    W: Word;
    W2: LongWord;

  Begin
    Result := True;
    If GetTickCount >= Time + 60000 Then Begin
      W := $FFFFFFFF;
      D := Now;
      Result := Result and WriteFile(hFile, W, SizeOf(W), W2, nil) and (W2 = SizeOf(W));
      Result := Result and WriteFile(hFile, D, SizeOf(D), W2, nil) and (W2 = SizeOf(D));
      Time := GetTickCount;
    End;
    W := Round(Temp * 100);
    If W = $FFFF Then W := $FFFE; // Spezialwert als Temperatur verhindern
    Result := Result and WriteFile(hFile, W, SizeOf(W), W2, nil) and (W2 = SizeOf(D));
  End;

Function TFileSave.Close: Boolean;
  Begin
    Result := CloseHandle(hFile);
  End;

Constructor TFileLoad.Create;
  Begin
    hFile := INVALID_HANDLE_VALUE;
  End;

Destructor TFileLoad.Destroy;
  Begin
    CloseHandle(hFile);
  End;

Function TFileLoad.Open(Const FileName: String): Boolean;
  Begin
    CloseHandle(hFile);
    Time := 0;
    hFile := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ,
      nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
    Result := hFile <> INVALID_HANDLE_VALUE;
  End;

Function TFileLoad.Load(Out Time: TDateTime; Out Temp: Single): Boolean;
  Var D: TDateTime;
    W: Word;
    W2: LongWord;

  Begin
    Result := ReadFile(hFile, W, SizeOf(W), W2, nil) and (W2 = SizeOf(W));
    If Result Then
      If W = $FFFFFFFF Then Begin
        Result := ReadFile(hFile, D, SizeOf(D), W2, nil) and (W2 = SizeOf(D));
        If Result Then Begin
          Result := Load(Time, Temp);
          Time := D;
        End;
      End Else Begin
        Time := Time + 1/24/60/60;
        Temp := W / 100;
      End
  End;

Function TFileLoad.Close: Boolean;
  Begin
    Result := CloseHandle(hFile);
  End;
Delphi-Quellcode:
Uses Windows, SysUtils, Unit3;

Var FS: TFileSave;
  FL: TFileLoad;
  Temp: Single;
  Time: TDateTime;
  S: String;

Begin
  FS := TFileSave.Create;
  If not FS.Open('Project3.dat') Then
    Raise Exception.Create('TFileSave - create/open file');

// {wiederholen}
// Temp := Wert_holen;
// FS.Save(Temp);
// {/wiederholen}

  {test}
    FS.Save(12.3);
    Sleep(1000);
    FS.Save(4.56);
    Sleep(1000);
    FS.Save(78.9);
  {/test}

  FS.Close;



  FL := TFileLoad.Create;
  If not FL.Open('Project3.dat') Then
    Raise Exception.Create('TFileLoad - create/open file');

// {wiederholen}
// FL.Load(Time, Temp);
// Zeit_ausgeben := Time;
// Temperatur_ausgeben := Temp;
// {/wiederholen}

  {test}
    While FL.Load(Time, Temp) do Begin
      S := DateTimeToStr(Time) + ' = ' + FloatToStr(Temp);
      MessageBox(0, PChar(S), '', 0);
    End;
  {/test}

  FL.Close;
End;
Dieses könnte man jetzt noch um mehr TempWert erweitern (eventuell sogar mit einer dynamischen Anzahl) und falls sich das Messintervall mal ändern könnte, dann sollte man es auch noch mit in der Datei speichern.

Wertebereich: 0.00 <= Temp <= 655.36

und falls man Word durch SmallInt (für Temp) ersetzt, dann -327.68 <= Temp <= 327.67
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat