Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Datei Archiv (https://www.delphipraxis.net/12967-datei-archiv.html)

Zerolith 8. Dez 2003 09:29


Datei Archiv
 
Hallo!

jeder kennt es - vorallem von spielen. Diese übergroßen Ressourcen Dateien in denen alles drin ist :)
naja, ich möchte au so was probieren. Hab auch schon meine Anfänge. Aber komm leider nicht weiter. Hier ist meine
Klasse mit der ich das Realisieren möchte. Aber es Funktioniert leider nicht so.

Ich hab auch keine Ahnung wie ich folgende Sachen realisieren soll.
+ Unterordner
+ Datei Suchen

Wie ihr seht hab ich es noch nichtmal geschafft die wirkliche Datei ins Archiv zu bekommen.
Bitte, helft mir!

(ich weiß nicht mal ob ich im richtigen Forum bin - eigtl. gehört das ja eher unter Datenbank aber das kann man ja sehen wie man will =) )

Danke, Daniel

Delphi-Quellcode:
...
Const BufferSize = 32;

type TArchivFile = Record
  FileName : String[100];
  FileSize : integer;
  FileContent : File;
  Inserted : TDateTime;
  Modified : TDateTime;
  Status : smallint;
  Visible : Boolean;
end;

type TZPAKArchiv = class
 private
   TArchiv : File of TArchivFile;
    function GetCount: Integer;
 public
   Constructor Create;
   procedure OpenArchiv(filename : String);
   procedure CloseArchiv;
   procedure DeleteFile(Position : LongWord);
   function ReadFile(Position : LongWord) : TArchivFile;
   procedure AddFile(ArchivFile : TArchivFile);
   procedure ModFile(ArchivFile : TArchivFile; Position : LongWord);
   property Count : Integer Read GetCount;
end;

implementation

{ TZPAKArchiv }

constructor TZPAKArchiv.Create;
begin
  inherited;
end;

procedure TZPAKArchiv.CloseArchiv;
begin
 CloseFile(TArchiv);
end;

procedure TZPAKArchiv.OpenArchiv(filename : String);
begin
  AssignFile(TArchiv, filename);
  if FileExists(filename) then ReSet(TArchiv) else ReWrite(TArchiv);
end;

function TZPAKArchiv.ReadFile(Position: LongWord): TArchivFile;
begin
  if (Position < 0) or (Position >= FileSize(TArchiv)) then Exit
  else
  begin
    Seek(TArchiv, Position);
    read(TArchiv, Result);
  end;
end;

procedure TZPAKArchiv.DeleteFile(Position: LongWord);
var Buffer : array[0..BufferSize - 1] of TArchivFile;
    i, p : Integer;
    StartRecord, EndRecord : Integer;
    Max : Integer;
begin
  Seek(TArchiv, Position-1);
  StartRecord := Position+1;
  EndRecord := Position;
  While StartRecord < EndRecord do
  begin
    Max := BufferSize;
    if Max > EndRecord - StartRecord then
      Max := EndRecord - StartRecord;
    Seek(TArchiv, StartRecord);
    for i := 0 to Max -1 do
      Read(TArchiv, Buffer[i]);
    Seek(TArchiv, StartRecord-1);
    for i := 0 to Max - 1 do
      Write(TArchiv, Buffer[i]);
    inc(StartRecord);
  end;
  Truncate(TArchiv);
end;

procedure TZPAKArchiv.AddFile(ArchivFile: TArchivFile);
var Buffer : Array[0..BufferSize - 1] of TArchivFile;
    i, p : integer;
begin
  Seek(TArchiv,0);
  p := 0;
  while not eof(TArchiv) do
  begin
   Read(TArchiv, Buffer[p]);
   inc(p);
  end;
  closeFile(TArchiv);
  Buffer[p+1].FileName := ArchivFile.FileName;
  Buffer[p+1].FileSize := ArchivFile.FileSize;
//  Buffer[p+1].FileContent := ArchivFile.FileContent;
  Buffer[p+1].Inserted := ArchivFile.Inserted;
  Buffer[p+1].Modified := ArchivFile.Modified;
  Buffer[p+1].Status := ArchivFile.Status;
  Buffer[p+1].Visible := ArchivFile.Visible;
  ReWrite(TArchiv);
  for i := 0 to p do Write(TArchiv, Buffer[i]);
end;

procedure TZPAKArchiv.ModFile(ArchivFile: TArchivFile; Position: LongWord);
var Datensatz : TARchivFile;
begin
  Seek(TArchiv, Position-1);
  Datensatz.FileName := ARchivFile.FileName;
  Datensatz.FileSize := ArchivFile.FileSize;
//  Datensatz.FileContent := ArchivFile.FileContent;
  Datensatz.Inserted := Archivfile.Inserted;
  Datensatz.Modified := Archivfile.Modified;
  Datensatz.Status := ArchivFile.Status;
  Datensatz.Visible := ArchivFile.Visible;
  write(TArchiv, Datensatz);
end;

function TZPAKArchiv.GetCount: Integer;
begin
  Result := FileSize(TArchiv)-1;
end;
...

scp 8. Dez 2003 10:42

Re: Datei Archiv
 
Also, die Eckdaten der Datei kannst du ja so am Anfang des Archivs speichern. Den Inhalt der Datei ebenfalls im Record zu speichern wäre zwar nicht unmöglich, aber nich sehr günstig. Ich würde statt
Delphi-Quellcode:
FileContent : File;
Delphi-Quellcode:
FileContentOffset : Cardinal;
verwenden und die Inhalte der Dateien per TFileStream (siehe OH) nach den records in das Archiv schreiben. FileContentOffset ist dann die Position der Daten der jeweiligen Datei im Archiv. Du kannst diese dann z.B. mit
Delphi-Quellcode:
var
  fs : TFileStream;
  fsData : TFileStream;
//..
begin
  fs := TFileStream.Create('C:\meine.pak', fmOpenRead);
  fsData := TFileStream.Create(Datensatz.FileName, fmOpenReadWrite);
  try
    fs.Seek(Datensatz.FileContentOffset, soFromBeginning);
    fsData.CopyFrom(fs, Datensatz.FileSize);
  finally
    fsData.Free;
  end;
end;
einlesen.

Zerolith 8. Dez 2003 10:59

Re: Datei Archiv
 
hmm... versteh was du meinst. Aber ich weiß leider nicht wie ich das machen soll.

Woher bekomme ich den Offset bzw. wie kann ich ihn setzen?

Danke!

scp 8. Dez 2003 11:51

Re: Datei Archiv
 
Liste der Anhänge anzeigen (Anzahl: 1)
Habe mal ein kleines Beispiel geschrieben, ist nicht perfekt aber zeigt, wie meine Idee umsetzbar wäre.

Zerolith 8. Dez 2003 11:53

Re: Datei Archiv
 
Ich Schaus mir mal an Danke!

scp 8. Dez 2003 11:57

Re: Datei Archiv
 
Hab grad noch was geändert, weil ne Kompo drin war, die du evtl. nicht drin hast.

Zerolith 8. Dez 2003 12:07

Re: Datei Archiv
 
Super! genau so etwas hab ich gebraucht.

Jetzt noch meine Frage: Wie mache ich das mit den unterordnern? Vorschläge, Ideen?
suchen dürfte ja relativ einfach gehen denk ich.

Nochmals danke!

scp 8. Dez 2003 12:36

Re: Datei Archiv
 
Also, um den Pfad mit zu speichern brauchst du ja nur das Laufwerk wegschneiden.

Aus D:\Pfad\nocheiner\eine.dat wird dann Pfad\nocheiner\eine.dat

Dann musst du nur noch später beim entpacken eine Prozedur erstellen, die nach und nach die unter ordner erstellt:

Delphi-Quellcode:
procedure MkSubDirs(DestDir : String; AFile : String);
var
  AFileName : String;
  CurDir : String;
//..
begin
  AFileName := AFile;
  CurDir := DestDir;
  while (Pos('\', AFilename) > 0) do
    begin
      CurDir := CurDir + Copy(AFilename, 1, Pos('\', AFilename)-1);
      Delete(AFilename, 1, Pos('\', AFilename));
      If not DirectoryExists(CurDir) then
        MkDir(CurDir);
      CurDir := CurDir + '\';
    end;
end;
Nicht getestet.

Zerolith 9. Dez 2003 21:15

Re: Datei Archiv
 
Danke!

hast mir sehr geholfen. Bastel gerade eine Klasse und eine Komponente zusammen.

hab noch ein paar Fragen:

- Kann ich den Header "einfach" so erweitern...
alt:
Delphi-Quellcode:
  TFileArchiveHeader = Record
    FileTag : array[0..3] Of Char;
    Count : Cardinal;
  end;
neu:
Delphi-Quellcode:
  TFileArchiveHeader = Record
    FileTag : array[0..3] Of Char;
    Password : String[25];
    Password : WordBool;
    Count : Cardinal;
  end;
... oder muss ich da in der Load und Save Funktion änderungen machen?
soweit ich weiß muss bei Strings ja eine Begrenzung sein (in diesem fall 25)
1. Stimmt das
und 2. muss das Passwort dann 25 Zeichen lang sein oder dürfen es weniger sein.

- Ich würde gerne besser damit arbeiten können.
damit meine ich: ich möchte in ein vorhandenes Package Dateien einfügen, bzw. Welche löschen. Oder sogar ändern.
[ Change ] hab grad gesehen dass du eine neue Version geuppt hast. Da ist das mit dem anfügen ja drin... [/ Change]

- Vielleicht noch einen Schritt weiter: Wäre es möglich (ja möglich bestimmt ich weiß :-) - bloß wie *G*) wenn man Größere Dateien einbindet einen Progressbalken fortschreiten zu lassen?


Ich habe mir für die Ordner das so gedacht. Also dass für die Ordner ein neuer Wert im Record angelegt wird
bsp:

Datei-1
filename : 'Testdatei1';
folder : '\Folder1\SubFolder1';

Datei-2
filename : 'Testdatei2';
folder : '\Folder1\'SubFolder2';

Dann kann ich in meine Abgeleiteten TListView komponente schön die einzelnen Ordner anzeigen. Mit nem Filter oder so. Muss i mir no was einfallen lassen.


So... genug Text so spät -ehhh Früh am Morgen *G*
Danke für die Aufmerksamkeit

Daniel

SirThornberry 9. Dez 2003 21:48

Re: Datei Archiv
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, besser spät als nie - hab da vor einiger zeit schonmal sowas gebastelt - musst du nur noch anpassen wegen deinem ladebalken - also einfach ne callbackfunktion reinbasteln und fertsch. Alternativ könntest du das ganze auch in ner simplen zipdatei organisieren. In der Zipdatei gibts noch einen ordner "komponenten" oder so. In dem sind noch 3 komponenten die für das demo benötigt werden sowie die filepack-komponente. Einfach die pas datein einem package hinzufügen und nicht vergessen die "*.dcr" datein aus dem package zu löschen sonst kommts zu dem fehler duplicate resources oder so


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:56 Uhr.
Seite 1 von 2  1 2      

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 by Thomas Breitkreuz