Einzelnen Beitrag anzeigen

Chewie

Registriert seit: 10. Jun 2002
Ort: Deidesheim
2.886 Beiträge
 
Turbo Delphi für Win32
 
#10

Re: Speichern von Baumstrukturen

  Alt 10. Okt 2003, 17:03
Ich hab in den letzten paar Wochen nur wenig dran gemacht, aber jetzt hab ich ein Problem, das sehr seltsam ist.

Ich speichere die Daten jetzt typisiert, ich hab zwar noch nicht überprüft, ob die richtigen Daten in der richtigen Reihenfolge gespeichert werden, aber ich prüfe, ob Größe der Datei = Anzahl der gefundenen Dateien * Größe des Records. Das klappt, da (noch) die Datengröße statisch ist.
Jetzt passiert etwas Merkwürdiges: Wenn ich den Algo testweise auf ein kleines Verzeichnis (rund 100 Dateien und Ordner) anwende, ist die Datei so groß wie erwartet. Wende ich ihn jedoch auf größere Verzeichnisse an, ist die Datei größer als erwartet, es wurden also mehr Daten von Dateien eingetragen, als Dateien da sind . Findet jemand den Fehler?

Die Dateien werden so eingelesen:

Delphi-Quellcode:
function TFiles.ReadFiles(Volume: String): Integer;
begin
  //Variablen vorbereiten
  FFileList := nil;
  SetLength(FFileList, flInitialLength);
  FFileListHighPos := -1;
  FRootNode.Free;
  FRootNode := TFileNode.Create;

  //Suchvorgang starten
  Result := RecurseProc(Volume, nil);
end;
Wobei RecurseProc so aussieht:
Delphi-Quellcode:
function TFiles.RecurseProc(Path: String; Node: TFileNode): Integer;
var
  SearchRec: TSearchRec;
  noFile: Boolean;
const
  Mask = '*.*'; //die zur Dateisuche verwendete Maske (*.* für alle Dateien)
begin
  Result := 0;

  //sicherstellen, dass Pfad mit Backlash endet
  if (Path[Length(Path)] <> '\') and (Path[Length(Path)] <> '/') then
    Path := Path + '\';

  if Node = nil then Node := FRootNode; //Standard-Rootnode setzen

  if FindFirst(Path + Mask, faAnyFile, SearchRec) <> 0 then Exit;

  //Suchschleife läuft als Endlosschleife, da vor UND nach Abbruchbedingung Code
  //ausgeführt werden muss
  while True do
  begin
    //prüfen auf Self- und Parent-Referenz
    if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
      noFile := False
    else
      noFile := True;

    if not noFile then
    begin
      //falls Ordner gefunden wurde:
      //- Zeiger auf erste ChildNode erstellen
      //- weiter mit Dateien in diesem Ordner
      if SearchRec.Attr and faDirectory = faDirectory then
      begin
        Node.FFirstChild := TFileNode.Create;
        Result := Result + RecurseProc(Path + SearchRec.Name, Node.FFirstChild);
      end;

      //Datenrecord über Dateieintrag füllen
      Node.FData.FullPath := Path + SearchRec.Name;
      Node.FData.AbsIndex := FFileListHighPos + 1;
      Node.FData.Size := SearchRec.Size;

      //sicherstellen, dass das Array groß genug ist
      EnsureListSize;

      //Eintrag in Array eintragen
      Inc(FFileListHighPos);
      FFileList[FFileListHighPos] := Node;

      Inc(Result);
    end;

    //nächstes Element suchen und prüfen auf Abbruchbedingung
    if FindNext(SearchRec) <> 0 then Break;

    if not noFile then
    begin
      //nur wenn ein nächstes Element vorhanden ist wird der Zeiger auf das nächste
      //Element gesetzt
      Node.FNext := TFileNode.Create;
      Node := Node.FNext;
    end;
  end;
  FindClose(SearchRec);
end;
Die Dateien werden so gespeichert:
Delphi-Quellcode:
class procedure TTreeFile.SaveToFile(RootNode: TTFNode; Filename: String);
var
  FilePos: Integer;
  
  procedure AddToStream(TFStream: TFileStream; Level: Word; TFNode: TTFNode);
  var
    Size: Word;
  begin
    //1. Schritt: Speichern der RootNode
    Size := TFNode.GetData.Size;
    TFStream.Position := FilePos;
    TFStream.Write(Level, 2);
    TFStream.Write(Size, 2);
    TFStream.Write(TFNode.GetData.PData^, Size);
    FilePos := TFStream.Position;

    //2. Schritt: evtl. Aufruf mit dem ersten Kind
    if TFNode.HasChildren then
    begin
      AddToStream(TFStream, Level + 1, TFNode.GetFirstChild);
    end;

    //3. Schritt: evtl. Aufruf mit dem nächsten Bruder
    if TFNode.HasBrethren then
    begin
      AddToStream(TFStream, Level, TFNode.GetNext);
    end;
  end;

var
  TFStream: TFileStream;
begin
  TFStream := TFileStream.Create(Filename, fmCreate or fmShareDenyNone);
  try
    FilePos := 0;
    AddToStream(TFStream, 0, RootNode);
  finally
    TFStream.Free;
  end;
end;
Wär super, wenn mir jemand helfen könnte, da ich in dem Code keinen Fehler mehr entdecke (Speziell die Save-Prozedur ist interessant, denn die ReadFiles-Methode scheint soweit richtig zu sein.
Martin Leim
Egal wie dumm man selbst ist, es gibt immer andere, die noch dümmer sind
  Mit Zitat antworten Zitat