Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Datei-/Verzeichnisname als DatenTyp (https://www.delphipraxis.net/158152-datei-verzeichnisname-als-datentyp.html)

Sir Rufo 7. Feb 2011 19:36


Datei-/Verzeichnisname als DatenTyp
 
Liste der Anhänge anzeigen (Anzahl: 4)
Da ich von Haus aus ein sehr fauler Mensch bin :mrgreen: regt mich das immer wiederkehrende Rumgefuddel mit dem Handling von Datei- und Verzeichnisnamen immer wieder auf.

Also war ich etwas fleißig um wieder faul sein zu können und habe einen Datentypen für Datei- und Verzeichnisnamen erstellt.

Umgesetzt wurde dieses mittels eines Records und überladenen Operatoren, damit die Verwendung so einfach von der Hand geht wie mit einem String. Der Vorteil hierbei ist aber, dass dieser Datentyp die Environment-Variablen von Windows berücksichtigt und auflöst.

Somit ist also folgendes möglich:
Delphi-Quellcode:
MyFileName := '%UserProfile%\Meine Datei.txt';
ShowMessage( MyFileName ); // Zeigt "C:\Users\Sepp\Meine Datei.txt" an
Und da es so schön war, habe ich noch diverse andere schicke Sachen eingebaut.
Einen Großteil kann man sich mit der beigefügten Exe-Datei (FileNameDataType.zip) ansehen und direkt ausprobieren.
Code:
{ +==========================================================================
  | TFileName = record
  +==========================================================================
  | Ein Record zur Vereinfachung des Dateinamen-Handlings
  |
  | Akzeptiert als Dateinamen auch die Environment-Variablen und übersetzt
  | diese automatisch.
  |
  | FileName := '%SYSTEMDRIVE%\%USERNAME%\Meine Datei.txt';
  |
  | Eigene Environment-Variablen können gesetzt werden. Diese dürfen auch
  | Environment-Variablen des Systems beinhalten.
  | (Default wird die Variable $(app) mit dem Pfad der Anwendung belegt)
  |
  | FileName := '$(app)\Meine Datei.txt'
  |
  | Implizite Umwandlungen:
  | -----------------------
  | FileName (String)     => 'C:\Sepp\Meine Datei.txt' (Dateiname)
  |
  | Eigenschaften (read/write):
  | ---------------------------
  | FileName.Raw          => '%SYSTEMDRIVE%\%USERNAME%\Meine Datei.txt'
  | FileName.Path         => 'C:\Sepp\'
  | FileName.FileName     => 'Meine Datei.txt'
  | FileName.Extension    => '.txt'
  |
  | Funktionen:
  | -----------
  | FullName (String)          => Kompletter gewandelter Dateiname
  | Exists (Boolean)           => Existiert die Datei
  | Creation (TDateTime)       => Zeitpunkt der Erstellung
  | LastAccess (TDateTime)     => Zeitpunkt des letzten Zugriffs
  | LastWrite (TDateTime)      => Zeitpunkt der letzten Änderung
  | Attributes (Cardinal)      => Attribute
  | Size (Int64)               => Größe
  | PathExists (Boolean)       => Existiert der Pfad
  | ForcePath (Boolean)        => Legt den Pfad an
  |                                (ForceDirectories)
  | Delete (Boolean)           => Löscht die Datei auf dem Datenträger
  |                                (DeleteFile)
  | Rename( string ) (Boolean) => Benennt die Datei auf dem Datenträger um
  |                                (RenameFile)
  |
  | Methoden:
  | =========
  | cd( string )               => Wechselt das Verzeichnis (relativ)
  | Burn                       => Wandelt einen relativen Pfad in Raw in
  |                                einen absoluten Pfad um
  | EnhanceEnvironmentLocal    => Erweitert die lokale Variablenliste
  |                                diese hat Vorrang vor der globalen
  |
  | Klassen-Methoden:
  | =================
  | EnhanceEnvironment         => Erweitert die globale Variablenliste
  +========================================================================== }
Code:
{ +==========================================================================
  | Beispiele
  +==========================================================================
  | 1. Environment-Variablen
  | ------------------------
  |
  | a)
  | FileName := '%systemroot%\Test.txt';
  | // FileName => 'C:\Windows\Test.txt'
  |
  | b)
  | FileName := '%systemdrive%\%username%\Test.txt';
  | // FileName => 'C:\Sepp\Test.txt'
  |
  | 2. Eigene Environment-Variablen
  | -------------------------------
  |
  | a) global
  | TFileName.EnhanceEnvironment( 'Daten', 'C:\Meine Daten\%username%' );
  | FileNameA := '$(Daten)\Test.txt';
  | FileNameB := '$(Daten)\Test.txt';
  | // FileNameA => 'C:\Meine Daten\Sepp\Test.txt'
  | // FileNameB => 'C:\Meine Daten\Sepp\Test.txt'
  | TFileName.EnhanceEnvironment( 'Daten', 'C:\Meine Daten\%computername%' );
  | // FileNameA => 'C:\Meine Daten\SeppSeinPC\Test.txt'
  | // FileNameB => 'C:\Meine Daten\SeppSeinPC\Test.txt'
  |
  | b) lokal
  | FileNameA := '$(Daten)\Test.txt';
  | FileNameB := '$(Daten)\Test.txt';
  | // FileNameA => 'C:\Meine Daten\Sepp\Test.txt'
  | // FileNameB => 'C:\Meine Daten\Sepp\Test.txt'
  | FileNameA.EnhanceEnvironmentLocal( 'Daten', 'C:\Meine Daten\Temp\' );
  | // FileNameA => 'C:\Meine Daten\Temp\Test.txt'
  | // FileNameB => 'C:\Meine Daten\Sepp\Test.txt'
  | FileNameA.EnhanceEnvironmentLocal( 'Daten', '' );
  | // FileNameA => 'C:\Meine Daten\Sepp\Test.txt'
  | // FileNameB => 'C:\Meine Daten\Sepp\Test.txt'
  |
  | 3. Relative Pfade (aktueller Pfad ist C:\Test\)
  | -----------------------------------------------
  |
  | a)
  |
  | FileName := '..\Test.txt';
  | // FileName    => 'C:\Test.txt'
  | // FileName.Raw => '..\Test.txt'
  | FileName.Burn;
  | // FileName    => 'C:\Test.txt'
  | // FileName.Raw => 'C:\Test.txt'
  |
  | b) mit Environment-Variable
  |
  | FileName := '..\%username%\data\..\Test.txt';
  | // FileName    => 'C:\Sepp\Test.txt'
  | // FileName.Raw => '..\%username%\data\..\Test.txt'
  | FileName.Burn;
  | // FileName    => 'C:\Sepp\Test.txt'
  | // FileName.Raw => 'C:\%username%\Test.txt'
  |
  | c) aber..
  |
  | FileName := '..\%username%\..\Test.txt';
  | // FileName    => 'C:\Test.txt'
  | // FileName.Raw => '..\%username%\..\Test.txt'
  | FileName.Burn;
  | // FileName    => 'C:\Test.txt'
  | // FileName.Raw => 'C:\Test.txt'
  |
  | d) cd
  |
  | FileName := 'C:\%username%\Test.txt';
  | FileName.cd( '..' );
  | // FileName => 'C:\Test.txt'
  | // FileName.Raw => 'C:\%username%\..\Test.txt'
  |
  | 4. Eigenschaften
  | ----------------
  |
  | FileName := 'C:\%username%\Test.txt';
  | FileName.Path := '%systemroot%';
  | // FileName.Raw => '%systemroot%\Test.txt'
  | FileName.FileName := 'Meine Datei.txt';
  | // FileName.Raw => '%systemroot%\Meine Datei.txt'
  | FileName.Extension := '.ini';
  | // FileName.Raw => '%systemroot%\Meine Datei.ini'
  |
  | 5. Benutzung mit Format
  | -----------------------
  | Trotz der impliziten Umwandlung in einen String akzeptiert die Format-
  | Funktion diesen Record nicht als Parameter. Darum so:
  |
  | s := Format( 'Pfad und Dateiname: %s', [ FileName.FullName ] );
  | s := Format( 'nur der Dateiname: %s', [ FileName.FileName ] );
  |
  +========================================================================== }
Ich bitte auch um sinnvolle Vorschläge (fertige Codeteile sind auch immer willkommen) zum Erweitern der Unit.

Sollte ab Delphi 2006 lauffähig sein, da ab der Version die überladenen Operatoren möglich waren.

Sodele, es gibt ein kleines Update.

Code:
Historie:

  | v1.2 - 11.02.2011
  | - Bei der Verwendung in einem Thread kam es teilweise zu einem Fehler
  |   bei der Verwendung der Magics. Ursache war die fehlende Initialisierung
  |   des Magigcs-Record. Bei jeder Änderung des Namens wird nun der Magics-
  |   Record initialisiert
  +--------------------------------------------------------------------------
  | v1.1 - 09.02.2011
  | * Unterstützung auch für nicht UNICODE-Compiler
  | * _FileName: func SizeStr
  | * _FileName: prop FileNameWoExt
  | * _FileName: prop DirName
  | * _DirName: func HasAccessRights
  | * _DirName: func IsCurrentDir
  | * _DirName: func MakeCurrentDir
  | * _DirName: func CurrentDir
  | * _DirName: Files Enumerator für Dateien
  | * _DirName: Dirs Enumerator für Verzeichnisse
  | * interne dynamische Variablen
  |   $(Year), $(Month), $(Day), $(Hour), $(Minute), $(Second), $(MSecond),
  |   $(DayOfWeek) [=Son-Sam], $(DayOfWeekLong) [=Sonntag-Samstag],
  |   $(ProcessID), $(ThreadID), $(MainThreadID),
  |   $(GUID), $(IDX)
  | * Zum Festhalten der dynamischen Variablen (Zeit,GUID) gibt es
  |   die Eigenschaft Magics.Lock
  | * Zum Aktualisieren der gelockten dynamischen Variablen gibt es
  |   die Methode Magic.Refresh
  | * prop Magics.Idx
  | * prop Magics.IdxLength (Default=3)
  | * meth Magics.IncIdx( Step )
  | * meth Magics.DecIdx( Step )
  | + EnhanceEnvironment ist jetzt eine ausgelagerte procedure
  | + Die Ersetzung der Environment-Variablen in eine eigene proc ausgelagert
  | - _FileName: Bei der Zuweisung von Path wurde der Raw-Eintrag von
  |   FileName und Extension verändert
  | - _DirName: Teilweise wurde ein Pfad und kein Verzeichnisname zurück-
  |   geliefert
  | ! Burn schreibt jetzt den Datei-/Verzeichnisnamen fest

WM_CLOSE 7. Feb 2011 19:55

AW: Datei-/Verzeichnisname als DatenTyp
 
Thx, sowas suche ich schon lange, aber wie sieht es mit der Unicode- Unterstützung aus (kann mangels Delphi nicht testen)? Du sagst ja, es sollte mit D2006 kompatibel sein.:?:

Sir Rufo 7. Feb 2011 20:06

AW: Datei-/Verzeichnisname als DatenTyp
 
Zitat:

Zitat von WM_CLOSE (Beitrag 1080190)
Thx, sowas suche ich schon lange, aber wie sieht es mit der Unicode- Unterstützung aus (kann mangels Delphi nicht testen)? Du sagst ja, es sollte mit D2006 kompatibel sein.:?:

Entwickelt habe ich das unter D2010 da ist UniCode ja default mit drin.
Das mit dem D2006 bezog sich vor allem auf die überladenen Operatoren.

Für die nicht UniCode Delphi-Versionen müsste man wohl alle Strings als WideString deklarieren.

Mal sehen, wann ich das umsetzen kann :)

himitsu 7. Feb 2011 20:26

AW: Datei-/Verzeichnisname als DatenTyp
 
Zitat:

Trotz der impliziten Umwandlung in einen String akzeptiert die Format-Funktion diesen Record nicht als Parameter. Darum so:
Nja, da Format, bzw. das Open-Variant-Array "mehrere" Typen entgegennehmen kann, weiß der Compiler nicht, welchen Typen er nun genau nehmen soll (so intelligent, um nachzusehen, daß eigentlich nur der eine "String" möglich wäre, ist Delphi anscheinend leider nicht :cry: )

Delphi-Referenz durchsuchenExpandFileName/MSDN-Library durchsuchenGetFullPathName nimmt leider das aktuelle Arbeitsverzeichnis ... schön wäre es aber, wenn dein Code das Programmverzeichnis (der EXE) als Ausgangspunkt nutzen würde.
> also entweder selber Parsen
> oder das aktuelle Arbeitsverzeichnis ändern (danach natürlich wieder zurück)
- Es gibt leider nichts (zumindestens hab ich noch nichts gefunden),
welches wie GetFullPathName arbeitet und wo man selber einen Ausgangspfad angeben kann (es sei denn da wird ebenfalls geparst)

Wenn am Anfang 'A:\' bis 'Z:\' vorkommt, dann kannst du das GetCurrentDirectory/SetCurrentDirectory notfalls auch überspringen.


PS: MSDN-Library durchsuchenGetLongPathName und MSDN-Library durchsuchenGetShortPathName

Und dem Directory könnte man auch einen Enumerator verpassen, um dann voa For-In alle Dateien aufzulisten, bzw. mehrere Enumeratoren als Record-Funktion, für Dateien, Verzeichnisse und mit Parametern zur Auswahl. :angle2:


[add]
Operatoren, um _FileName und _DirName zu casten wären gut, damit dort die RAW-Werte übergeben werden und nicht über den String-Umweg diese Infos verloren gehn. Wobei man auch alles hätte in einen Typen packen können, um nicht casten zu müssen ... beim Zugriff auf Dir-Eigenschaften, bei einer Datei, einfach eine Exception auslösen.

Sir Rufo 7. Feb 2011 21:03

AW: Datei-/Verzeichnisname als DatenTyp
 
Zitat:

Zitat von himitsu (Beitrag 1080201)
Zitat:

Trotz der impliziten Umwandlung in einen String akzeptiert die Format-Funktion diesen Record nicht als Parameter. Darum so:
Nja, da Format, bzw. das Open-Variant-Array "mehrere" Typen entgegennehmen kann, weiß der Compiler nicht, welchen Typen er nun genau nehmen soll (so intelligent, um nachzusehen, daß eigentlich nur der eine "String" möglich wäre, ist Delphi anscheinend leider nicht :cry: )

War ja auch nur als Hinweis gedacht, damit sich niemand wundert :)
Zitat:

Zitat von himitsu (Beitrag 1080201)
Delphi-Referenz durchsuchenExpandFileName/MSDN-Library durchsuchenGetFullPathName nimmt leider das aktuelle Arbeitsverzeichnis ... schön wäre es aber, wenn dein Code das Programmverzeichnis (der EXE) als Ausgangspunkt nutzen würde.
> also entweder selber Parsen
> oder das aktuelle Arbeitsverzeichnis ändern (danach natürlich wieder zurück)
- Es gibt leider nichts (zumindestens hab ich noch nichts gefunden),
welches wie GetFullPathName arbeitet und wo man selber einen Ausgangspfad angeben kann (es sei denn da wird ebenfalls geparst)

Wenn am Anfang 'A:\' bis 'Z:\' vorkommt, dann kannst du das GetCurrentDirectory/SetCurrentDirectory notfalls auch überspringen.

PS: MSDN-Library durchsuchenGetLongPathName und MSDN-Library durchsuchenGetShortPathName

Nee, eine Pfadangabe "..\Pfad\Datei.dat" bezieht sich immer und überall auf das aktuelle Arbeitsverzeichnis. Das Verhalten möchte ich nicht ändern. Finde ich immer komisch, wenn auf einem System die gleichen Parameter und Befehle ein anderes Ergebnis liefern.

Für einen relativen Bezug zum Anwendungsverzeichnis nimmt man halt
Delphi-Quellcode:
MyFileName := '$(app)\..\Pfad\Datei.dat';
Zitat:

Zitat von himitsu (Beitrag 1080201)
Und dem Directory könnte man auch einen Enumerator verpassen, um dann voa For-In alle Dateien aufzulisten, bzw. mehrere Enumeratoren als Record-Funktion, für Dateien, Verzeichnisse und mit Parametern zur Auswahl. :angle2:

das werde ich auf jeden Fall noch übernehmen
Zitat:

Zitat von himitsu (Beitrag 1080201)
[add]
Operatoren, um _FileName und _DirName zu casten wären gut, damit dort die RAW-Werte übergeben werden und nicht über den String-Umweg diese Infos verloren gehn. Wobei man auch alles hätte in einen Typen packen können, um nicht casten zu müssen ... beim Zugriff auf Dir-Eigenschaften, bei einer Datei, einfach eine Exception auslösen.

Öh, die sind doch drin :gruebel:

Delphi-Quellcode:
MyFileName := '$(app)\..\Pfad\Datei.txt';
MyDirName := MyFileName;
ShowMessage( MyDirName.Raw ); // -> $(app)\..\Pfad
MyFileName := 'Datei.txt';
MyFileName := MyDirName;
ShowMessage( MyFileName.Raw ); // -> $(app)\..\Pfad\Datei.txt
Allerdings nur bei der Record-Definition _DirName, was auch ausreicht ;)

schlecki 20. Apr 2011 12:25

AW: Datei-/Verzeichnisname als DatenTyp
 
Hallo,

wo gibt es denn die insSpecialFolders.pas?

s.h.a.r.k 20. Apr 2011 12:31

AW: Datei-/Verzeichnisname als DatenTyp
 
Schau mal ans Ende des ersten Beitrags. Dort gibt es ein Link für den Download.

Oha, ich ziehe meine Antwort zurück. Hatte gedacht, dass die Datei im angehängten ZIP-File zu finden ist.

ABER: es gibt die Datei hier im Forum, und zwar genau hier

shmia 20. Apr 2011 12:54

AW: Datei-/Verzeichnisname als DatenTyp
 
Also irgendwie hast du teilweise das FileSystem-Objekt von VBScript nachprogrammiert.

Man könnte auch direkt die Microsoft Scripting Runtime als Typbibliothek importieren und benützen.
Das wäre mal ein interessanter Job herauszufinden in wie weit man diese ActiveX-DLL direkt in Delphi gebrauchen kann.
Vielleicht noch einige Hilfsfunktionen zu bequemeren Erzeugung der Objekte sowie eine Demo-Anwendung hinzu...

Jens01 20. Apr 2011 12:58

AW: Datei-/Verzeichnisname als DatenTyp
 
Ich glaub, die insSpecialFolders.pas braucht man gar nicht! Einfach aus den uses löschen.

schlecki 20. Apr 2011 13:25

AW: Datei-/Verzeichnisname als DatenTyp
 
Zitat:

Zitat von s.h.a.r.k (Beitrag 1096196)
ABER: es gibt die Datei hier im Forum, und zwar genau hier

danke für den Link, hätte ich auch selbst finden können :oops:

Zitat:

Zitat von Jens01 (Beitrag 1096201)
Ich glaub, die insSpecialFolders.pas braucht man gar nicht! Einfach aus den uses löschen.

das sieht tatsächlich so aus, aber man kann da vielleicht auch noch was draus gebrauchen :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:12 Uhr.
Seite 1 von 2  1 2      

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