![]() |
TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Nachdem ich ewig lange recherchiert habe, wie man komplette Ordnerinhalte kopiert (alle Dateien und Unterordner), habe ich nicht wirklich herausfinden können, wieviele Null-Terminatoren bei den Pfaden im TSHFileOpStruct benötigt werden.
![]() Manche Codes im INet benutzen TStrings oder AnsiString, andere benutzen TFileName. Die einen terminieren pFrom und pTo überhaupt nicht zusätzlich, andere mit 1 zusätzlichen #0, und wiederum andere mit 2 zusätzlichen #0. Erstaunlicherweise sind die meisten Beiträge, die ich dazu gefunden habe, aus den frühen 2000er Jahren. Da ist ja viel Zeit vergangen. Wie sieht das denn heute aus? Welcher Eingangs-Dateityp (für Source- und Destination-Path) muss mit wie vielen Terminatoren ergänzt werden, wenn er mit PChar() an pFrom und pTo übergeben wird? Im Moment benutze ich den folgenden Code, der TFileName als Typ für Source und Destination verwendet. Dabei werden keine zusätzlichen Null-Terminatoren benutzt. Ist das überhaupt in Ordnung? Leider konnte ich diesbezüglich keine Informationen zu TFileName finden.
Delphi-Quellcode:
Guido.
// Routine zum Kopieren von Dateien und Ordnern.
function SHCopyFile(Handle: THandle; szSource, szDestination: TFileName): Boolean; var ShellFileOperation: TSHFileOpStruct; begin Result := True; try with ShellFileOperation do begin Wnd := 0; wFunc := FO_COPY; pFrom := PChar(szSource); pTo := PChar(szDestination); fFlags := FOF_NOCONFIRMMKDIR or FOF_NOCONFIRMATION; end; SHFileOperation(ShellFileOperation); except Result := False; end; end; |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Eigentlich steht alles in dem verlinkten MS-Artikel drin:
Zitat:
Im Delphi würde ich das wohl so machen:
Delphi-Quellcode:
denn IIRC hängt der Cast zu PChar bereits ein NULL an.
PChar(szSource + #0);
Grüße Dalai |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Delphi hängt standardmäßig immer zwei Nullen an seine Strings an. (als Kompatibilität auch zu solchen Listen)
Also im Prinzip könnte man es hier auch weglassen, aber zur Dokumentation hänge ich auch meistens die richtige Anzahl der Nullen nochmals an, also diese #0#0 für Listen. (nur bei "einfachen" PChars lasse ich diese #0 weg) Und ja, hier sind es "eigentlich" zwei #0, denn es ist eine Liste von Pfaden, wobei als Listenende ein Leerstring definiert ist.
Delphi-Quellcode:
, also effektiv #0#0 am Ende.
'Datei1'#0 + 'Datei2'#0 + {ENDE} ''#0;
PS: Die RTTI nutzt sowas ebenfalls, z.B. bei der Namensliste für ENUMs, oder die StringListen in den Ressources. PS: ein PChar-Cast, von einem String aus, gibt immer einen "gültigen" Zeiger zurück. Ein leerer String ist zwar NIL, aber hier wird dann ein Zeiger auf eine Konstante mit #0#0 zurückgegeben. Wer für eine Funktion ein "echtes" NIL benötigt, wenn der String leer ist, der sollte mit Pointer casten
Delphi-Quellcode:
statt
Pointer(MyString)
Delphi-Quellcode:
.
PChar(MyString)
(einziger Nachteil des Pointer, dabei geht die Typprüfung bezüglich ANSI und Unicode verloren) |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
Wie viele #0's ergibt das denn?
PChar(szSource + #0);
Gibt es denn auch "zuviele" #0's? Wenn ein string in Delphi schon standardmäßig 2 #0 hat und ich z. B. eingebe:
Delphi-Quellcode:
Kann es dann passieren, dass pFrom nun 4 #0 am Ende hat, und die Funktion das als Leerstring für pTo auswertet?
pFrom := PChar(szSource + #0#0);
pTo := PChar(szDestination + #0#0); Wie sieht das denn mit TFileName aus, also mit wie vielen #0's ist TFileName abgeschlossen? |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
. Strings sind in Delphi AFAIK nicht nullterminiert (sie haben aber im Gegensatz zu nullterminierten Strings eine Längenangabe).
string
Grüße Dalai |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
|
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
PChar(szSource + #0) ==> Wie viele #0's ergibt das denn? ==> Mindestens zwei.
Gibt es denn auch "zuviele" #0's? ==> Kommt auf den Anwendungszweck an. Meistens nein, und in diesem Fall definitiv nicht. Kann es dann passieren, dass pFrom nun 4 #0 am Ende hat, und die Funktion das als Leerstring für pTo auswertet? ==> Nein. Wie bei MS beschrieben, liest die API-Funktion bis zum ersten doppelten NULL und stoppt dort. Die Einzelstrings sind mit einfachen NULLs voneinander getrennt. ... mit wie vielen #0's ist TFileName abgeschlossen? ==> TFileName ist nur ein Alias für einen
Delphi-Quellcode:
. Strings sind in Delphi AFAIK nicht nullterminiert (sie haben aber im Gegensatz zu nullterminierten Strings eine Längenangabe).
string
@Dalai Vielen Dank für die deutlichen Aussagen! :) |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Jain.
Delphi-Strings sind per-se nicht null-terminiert, da ihre Länge gespeichert und von Delphi verwendet wird. Beim ShortString (dem "String" aus TurboPascal und dem ersten Delphi) gibt es nur das Längen-Byte und keine explizite #0 am Ende. Bei den LongStrings (AnsiString/UTF8String/RawByteString/... und UnicodeString) gibt es aber als Optimierung auch die #0#0 am Ende, damit es ohne umkopieren direkt nach PChar gecastet werden kann. Der WideString ... OLE32-String ( ![]() Also Delphi/Pascal verwendet bei String-Operationen nur die Längenangabe, aber bei der Verwaltung wird hinter dem letzten Zeichen noch ein Bereich mit den #0#0 bereitgehalten. Beispiel: StrLen im C++ liest den String Zeichen für Zeichen und sucht die erste #0 (Ende-Anfang=Länge), während Length direkt den Längen-Integer ausliest. |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
Zitat:
Zitat:
function SHCopyFile(Handle: THandle; szSource, szDestination: TFileName): Boolean; ... pFrom := PChar(szSource + #0); pTo := PChar(szDestination + #0); Vielen Dank für eure Infos! :) |
AW: TSHFileOpStruct - Wieviele Null-Terminatoren braucht der Mensch?
TFileName ist kein Alias, es ist ein Nachfahre. :zwinker:
Delphi-Quellcode:
Definiert einen neuen Typ mit den selben Eigenschaften, welcher auch zuweisungskompatibel ist.
type
TFileName = type string; ^^^^ String ist sowas, wie Integer früher und NativeInt jetzt ist ... er ist ein Alias auf den nativen Typen des Compilers. * vor Delphi2009 war es der AnsiString * und gaaaaaanz früher war es kein Alias, da war es der Typ String, welcher jetzt ShortString heißt (aber der Einfachheit halber könnte man es da als Alias für den ShortString sehen) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:31 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