![]() |
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; ... |
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:
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
FileContentOffset : Cardinal;
Delphi-Quellcode:
einlesen.
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; |
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! |
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.
|
Re: Datei Archiv
Ich Schaus mir mal an Danke!
|
Re: Datei Archiv
Hab grad noch was geändert, weil ne Kompo drin war, die du evtl. nicht drin hast.
|
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! |
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:
Nicht getestet.
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; |
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:
neu:
TFileArchiveHeader = Record
FileTag : array[0..3] Of Char; Count : Cardinal; end;
Delphi-Quellcode:
... oder muss ich da in der Load und Save Funktion änderungen machen?
TFileArchiveHeader = Record
FileTag : array[0..3] Of Char; Password : String[25]; Password : WordBool; Count : Cardinal; end; 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 |
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
|
Re: Datei Archiv
Hallo!
Find ich toll! allerdings möchte ich gern an dem source von SCP weiterentwickeln, da ich mich da schnell einarbeiten konnte und es mir grad einen mords spass bereitet, und ich hoffe dass ihr mir dabei auch etwas weiter helft. Bis ich mich in deinen Quellcode eingearbeitet hab der naja relativ umfangreich ist - naja hoff du weißt was ich mein =) Aber trotzdem Danke! |
Re: Datei Archiv
Falls du noch Anregungen brauchst, kuck dir mal meine SFXTools an:
![]() |
Re: Datei Archiv
kann mir evtl Jemand (*SCP Angugg*) erklären.
Was ich machen muss wenn ich HEader erweiter? ich kriegs nicht hin.
Delphi-Quellcode:
so ist im Moment und SO möcht ichs haben:
TFileArchiveHeader = Record
FileTag : array[0..3] Of Char; Count : Cardinal; end;
Delphi-Quellcode:
(ich weiß oben hab i n Fehler gemacht)
TFileArchiveHeader = Record
FileTag : array[0..[b]4[/b]] Of Char; Password : String[25]; PWEnabled : WordBool; Count : Cardinal; end; Was muss ich alles ändern damit das funktioniert? Danke |
Re: Datei Archiv
Du musst nur statt
Delphi-Quellcode:
dies hier einsetzen:
fs.Read(Header, 8);
Delphi-Quellcode:
und statt dem
fs.Read(Header, SizeOf(TFileArchiveHeader));
Delphi-Quellcode:
das hier:
fs.Write(Header, 8);
CurOffset := 8;
Delphi-Quellcode:
fs.Write(Header, SizeOf(TFileArchiveHeader));
CurOffset := SizeOf(TFileArchiveHeader); |
Re: Datei Archiv
Danke =)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:00 Uhr. |
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-2025 by Thomas Breitkreuz