Entwickler-Ecke
Dateizugriff - mehrere Dateien verschieben
kradon - Mi 31.07.02 15:57
Titel: mehrere Dateien verschieben
Hallo zusammen,
ich habe ein Problem und zwar habe ich ein Verzeichnis
c:\dateien\
darin stehen folgende Dateien
test1.txt, test2.txt, test3.txt und test4.doc
ich möchte nun alle Dateien mit der Endung .txt in das Verzeichnis
d:\archiv\
verschieben (Quelldatei soll nach dem verschieben nicht mehr vorhanden sein).
So und um das Chaos perfekt zu machen können beliebig viele Dateien
mit beliebig vielen Endungen in dem Verzeichnis c:\dateien\ stehen.
Vielen Dank im voraus.
Gruß
Karsten
Klabautermann - Mi 31.07.02 17:10
Hallo,
die richtigen Dateien finden kannst du mit FindFirst, FindNext und FindClose. Verschieben kannst du mit der API funktion MoveFile.
Gruß
Klabautermann
Christian S. - Mi 31.07.02 17:22
So geht es auch ohne API. Ist allerdings (wahrscheinlich) etwas umständlicher, ich kenne die API-Funktion nicht. Meine Delphi-Hilfe weigert sich, sie zu finden! Frechheit!
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| VAR datei : tSearchRec; erfolg : Boolean; begin erfolg:=(FindFirst(quellverzeichnis+'\*.txt',faAnyFile,datei)=0); while erfolg do begin CopyFileTo(quellverzeichnis+'\'+datei.name,zielverzeichnis+'\'+datei.name); DeleteFile(quellverzeichnis+'\'+datei.name); erfolg := (FindNext(datei)=0); end; FindClose(datei); end; |
Wichtig: "CopyFileTo" steht in der Unit "IdGlobal"
MfG,
Peter
Klabautermann - Mi 31.07.02 17:45
Peter Lustig hat folgendes geschrieben: |
Meine Delphi-Hilfe weigert sich, sie zu finden! Frechheit! |
Weil sie in der API-Hilfe beschrieben ist. gebe mal MoveFile ein und drücke F1 (nicht Hilfe aufrufen und dann MoveFile eingeben). Ebenfalls sehr interessant (in diesem zusammenhang)
CopyFile und
DeleteFile.
Zitat: |
BOOL MoveFile(
LPCTSTR lpExistingFileName, // address of name of the existing file
LPCTSTR lpNewFileName // address of new name for the file
); |
Der aufruf sieht also so aus:
Quelltext
1: 2:
| IF MoveFile(pChar('C:\Autoexec.Bak'), pChar('C:\tmp\Autoexec.Bak')) THEN ShowMessage('Datei erfolgreich verschoben'); |
Das ganze ist übrigens auch in der Windows.Pas importiert, so das du in Formularunits nicht mal deine Uses-Klauses erweitern musst.
Gruß
Klabautermann
Christian S. - Mi 31.07.02 18:55
Hi!
Danke! So klappt das Anzeigen der Hilfe. Kannst Du mir sagen, wo ich eine Liste der API-Funktionen runterladen kann? (Oder wie ich die Informationen, die ja irgendwo auf meinem Rechner gespeichert sein müssen, auslesen kann?)
MfG,
Peter
Klabautermann - Mi 31.07.02 19:01
Hallo,
die Hife ist in deinem Startbutton eingetragen ;). Start->Programme->{Delphi}->Hilfe->Microsoft SDK.
Gruß
Klabautermann
Christian S. - Mi 31.07.02 19:12
Peinlich! :oops:
Danke,
Peter
GPF - Mi 31.07.02 19:55
Oder benutze doch gleich die Windows API Routinen zum Verschieben von Dateien:
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:
| function SHFileMove(Owner:Integer; FromFile, ToFile:string; Flags: word):boolean; function ConvertFile(FileName:string):PChar; var NewFile:string; begin NewFile:=Filename; while pos(';', NewFile)>0 do NewFile[pos(';', NewFile)]:=#0; NewFile:=NewFile+#0+#0; Result:=PChar(NewFile); end; const Aborted:boolean=true; var Struct: TSHFileOpStructA; begin with Struct do begin wnd:=Owner; wFunc:=FO_Move; PFrom:=ConvertFile(FromFile); pTo:=PChar(ToFile); fFlags:=Flags; fAnyOperationsAborted:=Aborted; hNameMappings:=nil; lpszProgressTitle:=nil; end; Result:=(SHFileOperationA(Struct)=0) and (not aborted); end; |
Ich habe die Funktion so angepaßt, daß sie genau Deinen Bedürfnissen gerecht wird. Da eine einzige Methode unter Windows sämtliche Dateioperationen durchführt (Kopieren, Verschieben, Löschen) sind die Parameter etwas schwierig zu handeln. Anstatt Wildcards zu nutzen kannst Du auch mehrere Dateien durch Semikolon getrennt als Quelle angeben. Windows arbeitet intern mit #0. Die Methode Convertfiles konvertiert alle ; in #0 und fügt an das Ende zweimal #0 an, damit Windows das Ende der Dateiliste erkennt.
Als Flagkomination empfehle ich Dir
FOF_FILESONLY or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR or FOF_SILENT. Genaueres dazu kannst Du in dem Windows SDK (nicht die Delphi Hilfe - wird aber mit Delphi ausgeliefert) unter dem Schlüsselwort
SHFileOperation nachlesen.
Owner kannst Du auf 0 setzen, sofern Du nicht den Windows eigenen Verschieben/Kopieren/Löschen-Dialog angezeigt bekommen möchtest (Flag FOF_SILENT zeigt diesen Dialog nicht an). Nimm ansonsten das Fensterhandle.
Als Beispiel zum Verschieben aller Textdateien benutze folgenden Einzeiler:
Quelltext
1:
| SHFileMove(Handle, 'c:\Quellordner\*.txt', 'c:\Zielordner', FOF_FILESONLY or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR or FOF_SILENT); |
Christian S. - Mi 31.07.02 20:19
Irgendwie glaube ich, dass die Methode von Klabautermann sehr viel einfacher ist. Wenn Du im Quelltext, den ich weiter oben geschrieben habe, "CopyFileTo" und "DeleteFile" durch die API-Funktion "MoveFile", wie von Klabautermann beschrieben, ersetzt, hast Du einen ziemlich kompakten und einfach verständlichen Code.
MfG,
Peter
GPF - Mi 31.07.02 20:29
Das ist wahr. Allerdings sollen die alten aus dem 16 bit Windows stammenden Funktionen auf Dauer ersetzt werden. Laut den jetzigen Ankündigungen von MS könnte dies schon beim nächsten Windows der Fall sein.
Abgesehen davon bin ich mir nicht sicher ob MoveFile, CopyFile, DeleteFile korrekt mit Wildcards und Unterverzeichnissen korrekt klar kommt.
Christian S. - Mi 31.07.02 20:54
Zitat: |
Abgesehen davon bin ich mir nicht sicher ob MoveFile, CopyFile, DeleteFile korrekt mit Wildcards |
Mit Wildcards müssen diese Funktionen bei dem gegebenen Code nicht zusammen arbeiten. Ob sie das überhaupt können, weiß ich nicht, wäre aber interessant nachzuschauen/auszuprobieren.
Zitat: |
und Unterverzeichnissen korrekt klar kommt. |
Was meinst Du damit?
MfG,
Peter
GPF - Mi 31.07.02 21:13
SHFileOperation akzeptiert auch Wildcards - damit wird Deine Dateiiterierungsroutine überflüssig.
Als Quell und Zielparameter akzeptiert diese Windows Routine auch Verzeichnisse. Es wäre ohne Probleme auch möglich zusätzlich einen Ordner zum Verschieben anzugeben. Der Code würde dann wie folgt aussehen:
Quelltext
1:
| SHFileMove(Handle, 'c:\Quellordner\*.txt;c:\Quellordner\MoveMeFolder', 'c:\Zielordner', FOF_FILESONLY or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR or FOF_SILENT); |
Damit werden also einerseits alle Textdateien aus dem Ordner c:\Quellordner\ verschoben - andererseits aber auch der Ordner MoveMeFolder inklusive aller Unterordner und Dateien. Ich bin mir nicht sicher ob MoveFile dies ebenso korrekt macht.
Klabautermann - Mi 31.07.02 23:46
Ja,
SHFileOperation ist um einiges mächtiger und Komplizierten. Was mich am mesten dran stört sind die Animationen. Lassen die sich unterdrücken?
Gruß
Klabautermann
GPF - Do 01.08.02 04:47
Natürlich, wie ich bereits gesagt habe kann man durch das Flag FOF_SILENT die Animation unterdrücken.
Klabautermann - Do 01.08.02 09:25
GPF hat folgendes geschrieben: |
Natürlich, wie ich bereits gesagt habe kann man durch das Flag FOF_SILENT die Animation unterdrücken. |
:oops: Peinlich, habe deine obriges Posting nur überflogen.
Ich schätze dann werde ich mir bei gelegenheit mal einfache Copy, move ... Befehle auf dieser Basis bauen.
Gruß
Klabautermann
kradon - Do 01.08.02 10:07
Titel: WOW
Also Leute,
erst mal vielen Dank für die ganzen Antworten, aber wenn ich mir hier euren Quellcode so anschaue komme ich mir ziemlich unwissend vor. *g*
Wäre nett wen jemand von euch einmal den Code mit ausführlichen Komentaren für Dummies versehen kann.
Gruß
Karsten
Christian S. - Do 01.08.02 12:06
Hi!
Eigentlich bin ich inzwischen auch der Meinung, dass der Code von GPF der Bessere ist, aber leichter ist mein Code mit der Ergängzung von Klabautermann.
Wenn Du den Code haben möchtest, kann ich Dir den gerne noch mal mit Kommentaren geben. Aber wie gesagt, ich glaube der von GPF ist besser.
Problem: ich bekomme ihn nicht ans Laufen. Die Funktion "SHFileOperation" steht zwar in der API-Hilfe, wir von Delphi aber nicht akzeptiert.
MfG,
Peter
Klabautermann - Do 01.08.02 13:35
Hallo,
@Peter Lustig: denke an das "uses ShellAPI"
@GPF: Ich habe mir das komando noch mal in der Hilfe angesehen. Dort fand ich die angabe, das dieser Befehl unter Windows NT nicht zur verfügung steht. Ich habe ihn vor einer Weile mal unter W2k erfolgreich eingestzt. Weist du ab welcher Version er auch auf der NT schiene läuft?
Gruß
Klabautermann
Christian S. - Do 01.08.02 14:10
Zitat: |
@Peter Lustig: denke an das "uses ShellAPI"
|
Ups! Damit funktioniert es jetzt.
In meiner Hilfe steht übrigens zu dem Befehl die Bemerkung "Now Supported on Windows NT".
MfG,
Peter
kradon - Do 01.08.02 15:20
Titel: Dummies
Hallo zusammen !!!
@Peter Lustig könntest du mir deinen Quellcode noch einmal per
Mail inklusive Kommentare zukommen lassen ? Sozusagen
zum selbststudium.
Bitte an:
kradon@web.de
@GPF Würde mich freuen, wenn du das auch machen könntest
Mal eine Frage an alle, wie lange Programmiert ihr eigentlich schon und
mit welcher Version von Delphi ?
Ich für meinen teil habe vor 1 Jahr angefangen und programmiere
mit Delphi 3.
Gruß
Karsten
Christian S. - Do 01.08.02 15:51
@kradon:
Dein Studienobjekt ist abgeschickt, kommt von der Adresse:
arthur_philip_dent_42@gmx.de
Ich arbeite mit Delphi 6 Enterprise. Ich programmiere seit ca. 8 Jahren mit Pausen. Angefangen mit TP, dann ziemlich lange mit Delphi 3 und seit zwei oder drei Monaten mit Delphi 6. Habe aber so gut wie ausschließlich mit VCL gearbeitet. Das war ein Fehler, den ich langsam ändern will...
MfG,
Peter
GPF - Do 01.08.02 16:54
Ok, ich werde dann mal einen Kommentarversuch starten. Eine Kopie schicke ich Dir auch per Email zu.
Zuerst aber kurz zu Deinen Fragen:
Ich programmiere aktiv seit knapp 12 Jahren. Damals noch mit Basic und Assembler auf meinem alten C64.
1995 habe ich dann zum ersten Mal Delphi erblickt.
Eine Schulversion von Delphi 1 lag bei einem Buchhändler für 199,- DM in den Regalen. Da dachte ich noch, es wäre ein Multimedia Autoren System :shock: . Naja, dummerweise hatte ich dann kurze Zeit später auch das Geld zusammen und bin hingedackelt um mir die kleine Box zu kaufen. Nach ersten Annäherungsversuchen war dann aber der eigentliche Zweck dieser CD gelüftet und nach ca. einem halben Jahr war ich bereits voll von Delphi überzeugt. Später erschien dann Delphi 2, welches ich mir dann auch umgehend gekauft habe. Meine Programmierarbeit habe ich dann aber lange Zeit unter Delphi 1 weitergeführt, da ich Win3.1 Kompatibilität für einen Job brauchte. Irgendwann als klar war, daß alle Win3.1 Rechner aufgegeben worden sind, bin ich auf Delphi 5 Enterprise umgestiegen und seitdem damit voll zufrieden. D6 habe ich mir zwar auch bereits angesehen (PE) - allerdings lohnt sich noch kein Update - die Änderungen sind zu marginal.
So, nun aber zu den Programmerklärungen:
Der Code selber ist eigentlich nicht schwer zu verstehen. Der wichtigen Hauptfunktion SHFileOperationA wird ein Record TSHFileOpStructA übergeben, welche Quelle, Ziel, Parameter enthalten - und natürlich auch, was gemacht werden soll (kopieren, löschen, bewegen, umbenennen). Das A hinter SHFileOPStructA und SHFileOperationA bedeutet lediglich, das ich Ansi Strings benutze. Das A kann auch weggelassen werden, dann werden ganz normale 8 bit Zeichen verwendet - oder benutze W, für WideStrings.
TSHFileOpStructA ist dabei wie folgt deklariert:
TSHFileOpStructA = _SHFILEOPSTRUCTA;
_SHFILEOPSTRUCTA = packed record
Wnd: HWND;
wFunc: UINT;
pFrom: PAnsiChar;
pTo: PAnsiChar;
fFlags: FILEOP_FLAGS;
fAnyOperationsAborted: BOOL;
hNameMappings: Pointer;
lpszProgressTitle: PAnsiChar; { only used if FOF_SIMPLEPROGRESS }
end;
Die Parameter müssen je nach Operation entsprechend gefüllt werden. Genaues liest Du besser dazu in der Windows SDK Hilfe unter SHFILEOPSTRUCT nach. Hier aber einige Hinweise:
wFunc benennt die auszuführende Funktion: FO_COPY, FO_MOVE (wie hier verwendet), FO_RENAME; FO_DELETE.
Von diesem Parameter hängen im Prinzip alle weiteren Eingaben ab.
Wnd bezeichnet das Fensterhandle, falls der Fortschrittsdialog von Windows bei den Operationen angezeigt werden soll. Soll dieser Dialog nicht Modal angezeigt werden - oder eben gar nicht, dann setze hier 0 ein.
PFrom bezeichnet die Quelle der Operationen. Hier können beliebig viele Dateien angegeben werden. Unter Windows müssen die Dateien durch #0 voneinander getrennt werden. Ich habe mir die Hilfsfunktion ConvertFile geschrieben, welche Semikolon durch #0 ersetzt. Eine Liste von Dateien wird durch #0#0 abgeschlossen. Dies übernimmt diese Hilfsprozedur ebenfalls. Damit erkennt Windows das Ende einer Liste.
Hierbei sind auch Verzeichnisse und Wildcards erlaubt.
pTo ist das Ziel. Beim Löschen kann dieser Parameter natürlich leer bleiben. Üblicherweise ist dieses ein einziger Pfad. Sollen mehrere Zieldateien angegeben werden, so muß FOF_MULTIDESTFILES als Flag mit übergeben werden. Außerdem muß für jede Quelldatei (bzw. Pfad) auch ein Zielpfad angeben werden. In einem solchen Fall gelten die selben Regeln wie bei dem Parameter pFrom (also #0, Wildcards, etc).
fFlags ist ebenfalls ein wichtiger Parameter. Hier werden einige zusätzliche Details angegeben. Hier eine kurze Übersicht aller erlaubten Parameter:
FOF_ALLOWUNDO: Undo Angaben mitspeichern - damit kann man z.B. Dateiobjekte in den Papierkorb verschieben
FOF_FILESONLY: Nur Dateien verwenden - keine Ordner
FOF_MULTIDESTFILES: siehe pTo
FOF_NOCONFIRMATION: Unterbindet sämtliche Abfragen und beantwortet diese mit "Immer" - wenn z.B. eine Zieldatei bereits existiert wird diese ohne Abfrage überschrieben
FOF_NOCONFIRMMKDIR: Verzeichnisse werden ohne Abfrage des Users angelegt
FOF_RENAMEONCOLLISION: Falls Zieldateien bereits existieren werden die Dateien umbenannt
FOF_SILENT: Unterbindet den Windows eigenen Fortschrittsdialog.
FOF_SIMPLEPROGRESS: Zeigt nur den Fortschrittsbalken an - aber keine Dateinamen
FOF_WANTMAPPINGHANDLE: Erstellt im Parameter hNameMappings ein Log aller Operationen mit Quell und Zieldatei. Ist dieser Parameter gesetzt, so muß hNameMapping vom Programmierer manuell wieder durch SHFreeNameMappings freigegeben werden.
fAnyOperationsAborted sollte selbsterklärend sein. Ist True falls eine Operation nicht erfolgreich durchgeführt worden ist. Berücksichtige, daß wenn Operationen nicht erfolgreich waren der Ursprungszustand NICHT wieder hergestellt wird!
lpszProgressTitle kannst Du setzen, wenn Du einen einfachen Fortschrittsbalken anzeigen lassen möchtest. Mit diesem Parameter kannst Du den Titel setzen. In diesem Fall muß allerdings FOF_SIMPLEPROGRESS gesetzt sein
Berücksichtige, daß Du nur PChars verwenden darfst, wenn Stringwerte angibst!
Das ist eine kurze Erklärung zu der Struktur TSHFileOPStructA.
Zu meinem Code:
Die Funktion ConvertFile ersetzt alle Semikolon durch #0 und gibt einen PChar zurück.
In der Verschiebeprozedur fülle ich einfach die Struktur mit den übergebenen und benötigten Verschiebe-Parametern. Ich habe mich entschieden, daß ich auch die Flags als Parameter der Hauptfunktion übergebe, da ich in meinen Programmen ab und zu einen Verschiebe-Dialog anzeigen lassen möchte.
Nicht benutze Werte setze ich auf nil (hNameMappings, lpszProgressTitle).
SHFileOperation ist selber auch eine Funktion und liefert 0 zurück wenn die Dateioperation erfolgreich ausgeführt worden ist.
Das ist eigentlich schon das gesamte Geheimnis.
Um nun Dateien zu kopieren mußt Du nur wFunc auf FO_COPY setzen - der Rest kann bleiben.
Möchtest Du Dateien Löschen, so setzte wFunc auf FO_DELETE und pTo auf nil. Natürlich solltest Du bei beidem mit den Flags spielen um das gewünschte Resultat zu erzielen.
kradon - Fr 02.08.02 10:11
Titel: Vielen Dank
So habe mir die Unterlagen gerade mal angeschaut
und werde sie nun durcharbeiten.
Damit wird sich dann warscheinlich meine Delphikenntnisse
verdoppel. :lol:
Gruß
Karsten
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!