Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - [Delphi] FilenameToFile und Andersrum
IhopeonlyReader - Fr 06.09.13 16:41
Titel: [Delphi] FilenameToFile und Andersrum
Guten Tag,
nachdem ich mein Verschlüsselungsprogramm geschrieben hatte, dachte ich mir, dass die Dateitypen oder namen sicherlich schon einiges über den Inhalt aussagen und ich diese deshalb ebenfalls "verschlüsseln" sollte.
Ich dachte einfach daran, den Dateinamen mit in die exe zu schreiben und einfach Datei für Datei zu "zählen" ( z.B. in "0" umzubennen), da die Filename Möglichkeiten sehr eingeschränkt sind.
Doch scheinbar selbst bei einem solch einfachen Problem verzweifel ich schon, ich habe meinen Quelltext "angeschaut" und dachte, theoretisch müsste es funktionieren. Evtl benutzte ich auch einfach nur falsche Rechte beim Filestream (gibt's irgendwo ne übersicht, wann man share oder normale etc. verwenden sollte?)
Hier mal meine Schreibmethode
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| procedure NameToFile( Path: String; i: integer = -1); var Dir, FileName, NFL: String; FPL: Word; FS: TFileStream; begin if not FileExists( Path ) then exit; Dir := ExtractFilePath(Path); FPL := length( Dir ); FileName := Copy( Path, FPL+1, length(Path)-FPL ); NFL := IntToStr( i ); while FileExists( Dir + NFL ) do begin inc( i ); NFL := IntToStr( i ); end; RenameFile( Path, NFL ); FS := TFileStream.Create( Dir + NFL, fmOpenReadWrite or fmShareDenyRead or fmShareDenyWrite ); try FPL := length( Filename ); FS.Size := FS.Size + FPL + 2; FS.Seek( -FPL-2, soFromEnd ); FS.WriteBuffer( Pointer(FileName)^, FPL ); FS.Seek( -2, soFromEnd ); FS.WriteBuffer( FPL, 2 ); finally FS.Free; end; end; |
Meine lese procedure
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure LoadNameFromFile( Path: String ); var FileName: String; FPL: Word; FS: TFileStream; begin if not FileExists( Path ) then exit;
FS := TFileStream.Create( Path, fmOpenReadWrite or fmShareDenyRead or fmShareDenyWrite ); try FS.Seek( -2, soFromEnd ); FS.Read( FPL, 2 ); FS.Seek( -FPL-2, soFromEnd ); FS.Read( Pointer(FileName)^, FPL ); FS.Size := FS.Size - FPL -2; finally FS.Free; end; RenameFile( Path, FileName ); end; |
warum klappt es nicht, sind die Rechte falsch? Hab ich etwas grundlegendes falsch gemacht, oder was ist falsch?
Das Umbennen klappt, aber das schreiben in die Datei und das laden aus der Datei nicht !, evt würde das laden klappen wenn das schreiben klappt..
Sinspin - Sa 07.09.13 07:49
Hi, lauf deine procedure NameToFile einfach mal im Einzelschritt durch und schau Dir an was in den Variablen zur Laufzeit steht. Ich denke Du kommst dann selber auf deinen Fehler.
IhopeonlyReader - Sa 07.09.13 13:26
vielen Dank, dass ich einer meldet :)
Sinspin hat folgendes geschrieben : |
Hi, lauf deine procedure NameToFile einfach mal im Einzelschritt durch und schau Dir an was in den Variablen zur Laufzeit steht. Ich denke Du kommst dann selber auf deinen Fehler. |
Und ich habe nun geschaut was darin steht, aber das ist alles so wie es soll !
Die Datei wird auch so umbenannt wie sie soll, aber der Dateiname (Filename) wird nicht in die Datei geschrieben. oder die lese Funktion funktioniert nicht.
Wenn du den Fehler so offensichtlich findest, dann schreib mir bitte eine Zeile wo deiner Meinung nach eine Variable "falsch" sein könnte.. ich selbst finde den fehler nicht :(
Edit: Beim schreiben gibt es keine fehler, aber die Datei wird nicht "größer".
Beim Lesen kommt die Meldung "Stream lesefehler"
Gerd Kayser - Sa 07.09.13 16:46
IhopeonlyReader hat folgendes geschrieben : |
Die Datei wird auch so umbenannt wie sie soll, aber der Dateiname (Filename) wird nicht in die Datei geschrieben. oder die lese Funktion funktioniert nicht. |
Versuche es mal so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
| procedure TMainform.Button1Click(Sender: TObject); var DateiNameAlt : String; DateiNameNeu : String; Laenge : Int64; FS : TFileStream; begin DateiNameAlt := 'f:\test.txt'; DateiNameNeu := 'f:\0.'; RenameFile(DateiNameAlt, DateiNameNeu);
Laenge := Length(DateiNameAlt) * SizeOf(DateiNameAlt[1]);
FS := TFileStream.Create(DateiNameNeu, fmOpenReadWrite or fmShareDenyRead or fmShareDenyWrite ); try FS.Position := FS.Size; FS.Write(DateiNameAlt[1], Laenge); FS.Write(Laenge, SizeOf(Laenge)); finally FS.Free; end; end;
procedure TMainform.Button2Click(Sender: TObject); var DateiNameAlt : String; DateiNameNeu : String; Laenge : Int64; FS : TFileStream; Gelesen : Integer; begin DateiNameAlt := 'f:\0'; FS := TFileStream.Create(DateiNameAlt, fmOpenReadWrite or fmShareDenyRead or fmShareDenyWrite ); try FS.Position := FS.Size - SizeOf(Laenge); FS.Read(Laenge, SizeOf(Laenge)); FS.Position := FS.Position - SizeOf(Laenge) - Laenge; SetLength(DateiNameNeu, Laenge); FS.Read(DateiNameNeu[1], Laenge); FS.Size := FS.Size - SizeOf(Laenge) - Laenge; finally FS.Free; end; RenameFile(DateiNameAlt, DateiNameNeu); end; |
Die ganzen Fehlerprüfungen usw. einzubauen überlasse ich Dir.
IhopeonlyReader - So 08.09.13 12:54
Vielen Dank Gerd Kayser,
deine proceduren klappen fast.
in Button1Click (schreibmethode) darf DateinameNeu aber kein Pfad sein !
Edit: Es muss scheinbar schon ein Pfad sein :O
also Renamefile( path, extractfilepath(path)+newfilename)
ich habe es so abgeändert, dass die ersten 3 Zeilen so aussehen:
Delphi-Quelltext
1: 2: 3: 4:
| if not OD.Execute then exit; DateiNameAlt := OD.Filename;; DateiNameNeu := Edit1.Text; |
dann klappt alles wunderbar :)
OD =OpenDialog...
Im Edit stand z.B. "0" drin. also eine einfache Ziffer. Die Umbenennung fand statt ! komischerweise wude auch der filestream erzeugt, aber wieso funktioniert
Delphi-Quelltext
1:
| FS := TFileStream.Create( '0', fmOpenReadWrite or fmShareDenyRead or fmShareDenyWrite ); |
es ist ja kein Pfad am anfang angegeben.
Weitere Änderungen sind bei dir, dass du nicht Seek sondern Position := verwendest und anstatt Pointer(String)^ verwendest du String[1]
daraufhin lies ich mir mal diese beiden Speicheraddressen vergleichen:
Delphi-Quelltext
1:
| Showmessage( IntToStr( Cardinal(@DateiNameAlt[1]) ) +#13#10+ IntToStr( Cardinal(Pointer( Dateinamealt ))) ); |
es waren dieselben!
Nach meheren Test, war scheinbar im Read-Ereignis folgende Zeile wichtig:
Delphi-Quelltext
1:
| SetLength(DateiNameNeu, Laenge); |
in der Schreib-procedure dagegen, ist nur die Änderung, dass dort nicht ein ganzer pfad, sondern nur der Dateiname vom neuem file dort steht..
mich wundert es dass es trotzdem funktionert :O
sicherheitshalber habe ich es zu:
Delphi-Quelltext
1:
| ExtractFilePath(DateiNameNeu)+DateiNameNeu |
umgeändert (im TFileStream.create)
aber die wichtige Änderung war eben das Setlength im Read Ereignis.
IhopeonlyReader hat folgendes geschrieben : |
Edit: Beim schreiben gibt es keine fehler, aber die Datei wird nicht "größer". |
Das die Größe der Datei nicht geändert wurde, stimmte scheinbar nicht, das muss ein Fehler im Windows-Explorer sein, da der Dateiname ja hinten angehängt ist!
Gerd Kayser - So 08.09.13 14:11
IhopeonlyReader hat folgendes geschrieben : |
Das die Größe der Datei nicht geändert wurde, stimmte scheinbar nicht, das muss ein Fehler im Windows-Explorer sein, da der Dateiname ja hinten angehängt ist! |
Der Windowsexplorer zeigt in der normalen Ansicht die Dateigrößen nie in Bytes an. Dazu muss man sich den Eigenschaftendialog der jeweiligen Datei ansehen. Im Übrigen benutze ich da gerne einen Hex-Editor, um mir direkt ansehen zu können, was in der Datei steht.
Der Source war nur ein funktionierendes Beispiel. Die ganze Anwendung zu schreiben, hatte ich nicht die Lust und Zeit. Schließlich habe ich hier einen Fulltimejob auf vier Pfoten. ;-) Und ab und zu ein Stündchen das neue Splinter Cell Blacklist zocken will ich ja auch noch. Der Haushalt muss ja auch geführt werden.
Ob man nun Seek oder Position verwendet, ist eigentlich Jacke wie Hose. Jeder hat da seine Vorlieben. Wichtig ist da nur das Ergebnis.
Wichtig ist nicht nur die Zeile mit dem SetLength.
Delphi-Quelltext
1:
| Laenge := Length(DateiNameAlt) * SizeOf(DateiNameAlt[1]); |
Bei den neueren Delphi-Versionen sind die einzelnen Zeichen der Strings größer als ein Byte. Diese Info würde ich zusätzlich zum Dateinamen und der Länge in der Datei abspeichern und beim Lesen auswerten. Spätestens dann, wenn Du auf eine neuere Delphi-Version umsteigst, hättest Du sonst ein Problem.
IhopeonlyReader - So 08.09.13 14:14
[quote="
Gerd Kayser"(679637)]
IhopeonlyReader hat folgendes geschrieben : |
Bei den neueren Delphi-Versionen sind die einzelnen Zeichen der Strings größer als ein Byte. Diese Info würde ich zusätzlich zum Dateinamen und der Länge in der Datei abspeichern und beim Lesen auswerten. Spätestens dann, wenn Du auf eine neuere Delphi-Version umsteigst, hättest Du sonst ein Problem. |
ja, aber die Projekte bleiben in D7 PE... wenn ich umsteige, werde ich D7 weiterhin behalten und nicht allle Projekte "umschreiben", allgemein hast du natürlich recht
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!