AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen FreePascal Array of Record per FileStream speichern
Thema durchsuchen
Ansicht
Themen-Optionen

Array of Record per FileStream speichern

Ein Thema von Glocke89 · begonnen am 29. Mär 2009 · letzter Beitrag vom 29. Mär 2009
Antwort Antwort
Benutzerbild von Glocke89
Glocke89

Registriert seit: 2. Mär 2007
Ort: Thüringen
80 Beiträge
 
Lazarus
 
#1

Array of Record per FileStream speichern

  Alt 29. Mär 2009, 15:01
Hallo,

ich habe ewig lange gegoogelt und konnte mein Problem dennoch nicht lösen

Folgende Situation:
Im Browserspiel OGame gibt es Spionageberichte (von den Planeten / Monden anderer Spieler). Damit unsere Allianz (sowas wie ein Clan) immer up-to-date ist im Bezug auf die Berichte, programmiere ich atm an einer kleinen Datenbank.
Diese enthält u.A. einen Record für die Erfassung der Informationen, diese wiederum werden in einem Feld gespeichert und sollen (als erster Schritt) in eine Datei geschrieben werden. Folgender Quellcode
Delphi-Quellcode:
type
  { TKoordinaten }
  TKoordinaten = record
    Galaxie: 1 .. 9;
    Sonnensystem: 1 .. 499;
    Position: 1 .. 15;
  end;

  { TTag }
  TTag = record
    Tag: 1 .. 31;
    Monat: 1 .. 12;
    Jahr: 1900 .. 3000;
  end;

  { TZeit }
  TZeit = record
    Stunde: 0 .. 23;
    Minute: 0 .. 59;
    Sekunde: 0 .. 60;
  end;

  { TSpioDB }
  TSpioDB = record
    Koordinaten: TKoordinaten;
    Mond: boolean;
    Tag: TTag;
    Zeit: TZeit;
    Spionagebericht: string;
    Autor: string;
  end;

  { TDB }
  TDB = array of TSpioDB;

  { TSpioFile }
  TSpioFile = File of TSpioDB;
Und hier die Speichern- und Laden-Unterprogramme (inklusive Funktion zur Bestimmung der Dateigröße):

Delphi-Quellcode:
{ GetFileSizeEx }
function GetFileSizeEx(const AFileName: string): Int64;
var
  F: TSearchRec;
begin
  Result := -1;
  if FindFirst(AFileName, faAnyFile, F) = 0 then
  begin
    try
      Result := F.FindData.nFileSizeLow or (F.FindData.nFileSizeHigh shl 32);
    finally
      SysUtils.FindClose(F);
    end;
  end;
end;

{ LoadDatenbank }
procedure LoadDatenbank(var db: TDB; var count: integer; s: string; var b: boolean);
var
  spiofile: TSpioFile;
  i, size, n: integer;
begin
  b := false;
  size := GetFileSizeEx(s);
  count := size div sizeof(TSpioDB);
  SetLength(db, count);
  try
    AssignFile(spiofile, s);
    Reset(spiofile);
    for i := Low(db) to (High(db) - 1) do
      Read(spiofile, db[i]);
    b := true;
  finally
    CloseFile(spiofile);
  end;
end;

{ SaveDatenbank }
function SaveDatenbank(db: TDB; s: string): boolean;
var
  spiofile: TSpioFile;
  i: integer;
begin
  result := false;
  try
    AssignFile(spiofile, s);
    Rewrite(spiofile);
    for i := Low(db) to (High(db) - 1) do
      Write(spiofile, db[i]);
    result := true;
  finally
    CloseFile(spiofile);
  end;
end;
Mein Problem ist jetzt: wenn ich Datensätze anlege (machen andere Unterprogramme fehlerfrei - hab mir nach der Eingabe welche ausgeben lassen) und abspeichere, dannach das Programm neu starte und die Datei öffnen will, werden u.A. "Spionagebericht: string" nicht geladen und können nicht ausgegeben werden.

Kann mir jemand helfen?

Wenn irgendwas unklar ist dann nochmal nachfragen, kann auch sein, dass ich jetzt irgendwas wichtiges vergessen habe

Danke im Vorraus

LG Glocke
Christian
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#2

Re: File of Array

  Alt 29. Mär 2009, 15:09
String kannst Du in einer typisierten Datei nicht verwenden. String enthält grob gesagt nur einen Zeiger auf die Zeichenkette, Du speicherst also nur den Zeiger.

Die Zeichen sind zudem von variabler Länge, was eine typisierte Datei auch nicht mag.

Entweder änderst Du String nach ShortString (also String[255]) oder wenn 255 Zeichen nicht reichen, dann array of Char oder anders Speicher-System.

In diesem Thread findet sich ein Beispiel, wie ein array of Char in einer typisierten Datei verwendet werden kann.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

Re: File of Array

  Alt 29. Mär 2009, 15:12
es gibt sogar schon tausende Theman zu dieser Angelegenheit ... der Letze ist nichtmal alt
http://www.delphipraxis.net/internal...t.php?t=154858
http://www.delphipraxis.net/internal...t.php?t=148570
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Glocke89
Glocke89

Registriert seit: 2. Mär 2007
Ort: Thüringen
80 Beiträge
 
Lazarus
 
#4

Re: File of Array

  Alt 29. Mär 2009, 15:15
Zitat von Satty67:
String kannst Du in einer typisierten Datei nicht verwenden. String enthält grob gesagt nur einen Zeiger auf die Zeichenkette, Du speicherst also nur den Zeiger.

Die Zeichen sind zudem von variabler Länge, was eine typisierte Datei auch nicht mag.

Entweder änderst Du String nach ShortString (also String[255]) oder wenn 255 Zeichen nicht reichen, dann array of Char oder anders Speicher-System.

In diesem Thread findet sich ein Beispiel, wie ein array of Char in einer typisierten Datei verwendet werden kann.
Och menno stimmt verdammt, naja nehm ich halt nen Array of Char.

/EDIT
dbengine.pas(166,26) Error: Incompatible types: got "Open Array Of Char" expected "Dynamic Array Of Char" wenn ich zB db[count - 1].Autor := a; machen will.

PS: String[255] reicht glaube ich nicht aus...
Christian
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#5

Re: File of Array

  Alt 29. Mär 2009, 15:26
Das Problem
Incompatible types: got "Open Array Of Char" expected "Dynamic Array Of Char" wird in den benanten Thread behandelt...

Nebenbei... es bleibt dabei... keine dynamischen Strukturen für eine typisierte Datei. Das gilt dann auch für ein Array.
  Mit Zitat antworten Zitat
Benutzerbild von Glocke89
Glocke89

Registriert seit: 2. Mär 2007
Ort: Thüringen
80 Beiträge
 
Lazarus
 
#6

Re: File of Array

  Alt 29. Mär 2009, 15:29
Ich merk gerade es geht auch ganz anders:
Die Spionageberichte kann ich auch direkt in die Unterpunkte "Rohstoffe", "Gebäude" etc. zerlegen, da reichen 255 Zeichen aus ... ich schau mir das mit dem Array of Char trotzdem der Vollständigkeit halber mal an.

Nochmal danke für die Erinnerung mit dem String, dass der nen Zeiger enthält

So... mittlerweile bin ich über diesen Thread auf die Idee gekommen das ganze mit StreamFile abzuspeichern:

Delphi-Quellcode:
procedure SaveDatenbank(x: TDB; Filename: String);
var fs: TFileStream;
     l, i: Integer;
begin
  fs := TFilestream.Create(Filename, fmCreate);
  try
    for i := 0 to High(x) do
    begin
      fs.Write(x[i].Koordinaten, SizeOf(TKoordinaten));

      fs.Write(x[i].Mond, SizeOf(boolean));

      fs.Write(x[i].Tag, SizeOf(TTag));

      fs.Write(x[i].Zeit, SizeOf(TZeit));

      l := Length(x[i].Spionagebericht);
      fs.Write(l, SizeOf(string));
      fs.Write(x[i].Spionagebericht, l);

      l := Length(x[i].Autor);
      fs.Write(l, SizeOf(string));
      fs.Write(x[i].Autor, l);
    end;
  finally
    fs.Free;
  end;
end;

// -----------------------------------------------------------------------------

function LoadDatenbank(Filename: String): TDB;
var fs: TFileStream;
    l, i: Integer;
begin
  fs := TFilestream.Create(Filename, fmOpenRead);
  try
    i := 0;
    while { hier fehlt mir irgendeine Bedingung } do
    begin
      fs.Read(Result[i].Koordinaten, SizeOf(TKoordinaten));

      fs.Read(Result[i].Mond, SizeOf(boolean));

      fs.Read(Result[i].Tag, SizeOf(TTag));

      fs.Read(Result[i].Zeit, SizeOf(TZeit));

      fs.Read(l, SizeOf(string));
      SetLength(Result[i].Spionagebericht, l);
      fs.Read(Result[i].Spionagebericht, l);

      fs.Read(l, SizeOf(string));
      SetLength(Result[i].Autor, l);
      fs.Read(Result[i].Spionagebericht, l);

      i := i + 1;
    end;
  finally
    fs.Free;
  end;
end;
Mir fehlt beim "Laden" die Bedingung wann meine Schleife (die alle Elemente auslesen soll) abbrechen soll.
Ich hab einen Zähler (i) eingefügt um die einzelnen Elemente des Arrays anzusprechen.
Christian
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:36 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