Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING) (https://www.delphipraxis.net/143985-datei-kopieren-ohne-cache-file_flag_no_buffering.html)

DevidEspenschied 27. Nov 2009 12:09


Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Hallo,

ich muss eine größere Datei mehrfach von Position A zu Position B kopieren. Position A ist hier eine CD und Position B ein temporäres Verzeichnis auf der Festplatte. Ab dem 2. Versuch spring allerdings der Windows-Cache ein und ich kann die CD quasi herausnehmen, obwohl der Vorgang weiterläuft.

Deswegen muss ich diesen Vorgang ohne den Windows-Cache durchführen.

Bisher habe ich folgendes zum Öffnen des Laufwerks:

Delphi-Quellcode:
function KopiereDatei(Laufwerk: Char; Datei : string) : Boolean;
var handle : THandle;
begin
  Result:=False;
  Handle:=CreateFile(PChar('\\.\' + Laufwerk + ':'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_NO_BUFFERING, 0);

  if Handle <> INVALID_HANDLE_VALUE then
  begin
    {hier müsste der Kopiervorgang starten}
  end;

  CloseHandle(Handle);
end;

begin
  if KopiereDatei('D', 'TESTFILE.DAT') = true then ShowMessage('Datei erfolgreich kopiert.') else ShowMessage('Fehler beim Kopieren der Datei.');
end;
Wie kann ich jetzt eigentlich die Kopieraktion implementieren? Muss das über BlockRead/BlockWrite mit einem Puffer geschehen?

Es gibt ja auch noch das Attribut FILE_FLAG_WRITE_THROUGH. Ist dieses als Alternative zu FILE_FLAG_NO_BUFFERING zu verwenden, oder kann man das zusätzlich machen?

Mithrandir 27. Nov 2009 12:19

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von devidespe
Es gibt ja auch noch das Attribut FILE_FLAG_WRITE_THROUGH. Ist dieses als Alternative zu FILE_FLAG_NO_BUFFERING zu verwenden, oder kann man das zusätzlich machen?

Beitrag dazu in der Knowledge Base

Luckie 27. Nov 2009 12:27

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Warum öffnest du das Laufwerk? Du musst die zu kopierende Datei mit entsprechenden Flags öffnen.

uoeb7gp 27. Nov 2009 22:52

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Hallo devidespe, ich hoffe es ist noch nicht zu spät für eine Warnung!

Wenn du hier

Delphi-Quellcode:
 
if Handle <> INVALID_HANDLE_VALUE then
  begin
    {hier müsste der Kopiervorgang starten}
  end;
mit WriteFile zu schreiben anfängst, zerstörst du dir MBR und oder MFT!!!

Du wirst dann eine Neupartitionierung und Formatierung, der Festplatte nicht verhindern können.

lg.

Mithrandir 28. Nov 2009 08:25

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von uoeb7gp
mit WriteFile zu schreiben anfängst, zerstörst du dir MBR und oder MFT!!!

Das müsstest du vielleicht mal genauer ausführen...

DevidEspenschied 28. Nov 2009 09:01

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zum Glück habe ich mir noch nicht den MBR zerstört. Danke für die Warnung.

Zitat:

Zitat von Luckie
Warum öffnest du das Laufwerk? Du musst die zu kopierende Datei mit entsprechenden Flags öffnen.

Mit normalen Dateifunktionen wie Assign, BlockRead/BlokWrite bzw. auch über Streams kann ich nicht arbeiten, da sie den Windows Cache verwenden. Existiert denn überhaupt noch eine andere Möglichkeit, um dies ohne den Windows Cache zu erledigen?

Mithrandir 28. Nov 2009 09:11

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Luckie wollte sagen, dass

Delphi-Quellcode:
Handle:=CreateFile(PChar('\\.\' + Laufwerk + ':'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_NO_BUFFERING, 0);
dir ein Handle auf das Laufwerk, nicht aber auf die Datei gibt, die du ja eigentlich haben willst. Deswegen vermutlich auch die panische Reaktion des Vorposters.

Zitat:

Mit normalen Dateifunktionen wie Assign, BlockRead/BlokWrite bzw. auch über Streams kann ich nicht arbeiten, da sie den Windows Cache verwenden.
Das ist - mit Verlaub - Schwachsinn. Wenn du die Funktionen nutzt, die Delphi bereitstellt, um mit dem Handle von CreateFile zu arbeiten, dann wird Delphi nicht das Handle spontan ändern und das FILE_FLAG_NO_BUFFERING herausnehmen.

Zitat:

Existiert denn überhaupt noch eine andere Möglichkeit, um dies ohne den Windows Cache zu erledigen?
Siehe Absatz vorher. Ansonsten:
MSDN-Library durchsuchenReadFile,MSDN-Library durchsuchenWriteFile

Was ich mich frage: Zu was soll das eigentlich gut sein? Wenn es dir um einen Benchmark geht, oder du prüfen möchtest, ob die CD in Ordnung ist, würde ich eher zu SPTI greifen...

DevidEspenschied 28. Nov 2009 09:24

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von Daniel G
Was ich mich frage: Zu was soll das eigentlich gut sein? Wenn es dir um einen Benchmark geht, oder du prüfen möchtest, ob die CD in Ordnung ist, würde ich eher zu SPTI greifen...

Es geht in der Tat um eine Art BurnIn-Belastungstest, bei dem das CD-Laufwerk gestresst werden soll. Dies kann aber nur geschehen, wenn konstant Daten vom Laufwerk gelesen werden und nicht etwa der Windows-Cache bemüht wird.

SPTI kann ich mir anschauen, das kannte ich noch nicht. Ansonsten denke ich, dass ReadFile/WriteFile ebenfalls ein Schritt in die korrekte Richtung ist.

Mithrandir 28. Nov 2009 10:32

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von devidespe
Es geht in der Tat um eine Art BurnIn-Belastungstest, bei dem das CD-Laufwerk gestresst werden soll. Dies kann aber nur geschehen, wenn konstant Daten vom Laufwerk gelesen werden und nicht etwa der Windows-Cache bemüht wird.

SPTI kann ich mir anschauen, das kannte ich noch nicht.

Jupp, stimmt. Dann würde ich aber die Daten, die ja eigentlich nicht gebraucht werden, in einen temporären Speicher schreiben, der bei jedem neuen Auslesen wieder überschrieben wird. So spart man sich das vollschreiben der Festplatte. Bedenke aber, dass man zum Nutzen von SPTI Adminrechte benötigt. Ich bin mir hundertprozentig sicher, es gab eine Möglichkeit, wie man das im Programmcode verhindern konnte und SPTI ohne Adminrechte nutzen konnte. Ich finde nur den Link nicht mehr... :wall:

Ansonsten kann man aber auch einfach die Richtlinien für den entsprechenden Nutzer anpassen, siehe: ImgBurn FAQ

CreateFile funktioniert natürlich auch... Wenn du noch ein bisschen weiter gucken möchtest, und C mächtig bist, kannst du hier mal schauen: http://www.cdtool.pwp.blueyonder.co.uk/workshop.htm

Und dann gibts ja auch noch Freeburner und die TISOLib, beides eher zum Ausschlachten.

DevidEspenschied 1. Dez 2009 09:34

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Danke Daniel G für die Links.

Im Grunde suche ich allerdings eine Lösung, die sich nicht nur für CD-Laufwerke, sondern gleichermaßen für Festplatten verwenden lässt. Soll heißen, dass eine größere temporäre Datei von einem Temp-Verzeichnis in ein anderes Temp-Verzeichnis kopiert werden soll.

Da scheint mir CreateFile die universelle Lösung zu sein. Ich muss nur noch herausbekommen, wie ich das auf Dateien anwende, da mein Beispiel im ersten Post ja nur ein Handle für das Laufwerk erzeugt.

himitsu 1. Dez 2009 09:37

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von devidespe
Ich muss nur noch herausbekommen, wie ich das auf Dateien anwende, da mein Beispiel im ersten Post ja nur ein Handle für das Laufwerk erzeugt.

Ja, wenn man einen Laufwerksnamen angibt, dann wird ein Laufwerkshandle erstellt
und jetzt rate mal, womit man ein Dateihandle bekommt. :angel:

DevidEspenschied 1. Dez 2009 10:00

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von himitsu
Ja, wenn man einen Laufwerksnamen angibt, dann wird ein Laufwerkshandle erstellt
und jetzt rate mal, womit man ein Dateihandle bekommt. :angel:

Es ist mir schon klar, dass der Laufwerksname um die Dateiposition sowie den Dateinamen zu erweitern ist. Ich suche zurzeit noch Beispiele, die den Einsatz von Readfile/WriteFile für das Kopieren beschreiben. Hier in der Suche wird das oft für serielle Schnittstellen verwenden.

Ich hatte noch überlegt, mit SHFileOperation zu arbeiten. Allerdings erlauben die Flags keine Umgehung des Windows-Caches.

himitsu 1. Dez 2009 10:18

Re: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Du öffnest einfach beide Dateien

einmal mir Leserechten und FILE_FLAG_NO_BUFFERING
und nochmal mit Schreibrechten und (FILE_FLAG_WRITE_THROUGH or FILE_FLAG_NO_BUFFERING)

und dann ließt du einfach mit ReadFile in einem Puffer und schreibst diesen in die andere Datei.

Vergiß aber nicht, es können nur ganze Sektoren gelesen und geschrieben werden.


Tipp: schau dir mal die Codes meines alten Hier im Forum suchenFileSplitters an :)


PS: du kannst auch mal mit hiermit spielen

Leserechte und FILE_FLAG_SEQUENTIAL_SCAN
Schreibrechte und (FILE_FLAG_SEQUENTIAL_SCAN or FILE_FLAG_WRITE_THROUGH)


genaueres zu den Parametern siehe MSDN-Library durchsuchenCreateFile


PSS: da es um Temp-Dateien geht, kann ich auch noch FILE_ATTRIBUTE_TEMPORARY empfehlen.

Benmik 25. Dez 2017 19:28

AW: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Es ist ja schon ein paar Tage her, aber vielleicht ist mittlerweile dies hier auch nicht uninteressant...

Ich benutze gerade die Umgehung des File Caches für den Vergleich von zwei Dateien.
Das Codegerüst sieht ungefähr so aus:
Delphi-Quellcode:
var i:integer;
    DatnameQuelle,DatnameZiel:string;
    HQuelle,HZiel:THandle;
    BufQuelle,BufZiel:TBytes;
    AnzBytesQ,AnzBytesZ:Cardinal;
const K256 = 256 * 1024;

HQuelle    := CreateFile(PChar(DatnameQuelle), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
HZiel      := CreateFile(PChar(DatnameZiel),  GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
Try
  If (HQuelle <> INVALID_HANDLE_VALUE) and (HZiel <> INVALID_HANDLE_VALUE) then begin
    Repeat
      ReadFile(HQuelle, BufQuelle[0], K256, AnzBytesQ, nil);
      ReadFile(HZiel, BufZiel[0], K256, AnzBytesZ, nil);
      If (AnzBytesQ <> AnzBytesZ) or not CompareMem(BufQuelle,BufZiel,K256) then begin
        break;
      end;
    until AnzBytesQ < K256;
  end;
Finally
  FileClose(HQuelle);
  FileClose(HZiel);
End;
(Der Wert der Konstante K256 stammt übrigens von hier, er sorgt auch für die Teilbarkeit durch 512.)
Ich frage mich aber, ist das eigentlich sinnvoll, den Cache hier zu umgehen? In meinem Szenario werden die Dateien nicht nochmal eingelesen, der Cache würde also keinen Vorteil bringen.

LTE5 25. Dez 2017 19:47

AW: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Hier stand Quatsch.

Hobby-Programmierer 25. Dez 2017 20:23

AW: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von Benmik (Beitrag 1389648)
Ich benutze gerade die Umgehung des File Caches für den Vergleich von zwei Dateien.

Zum Vergleich reicht doch das lesen der Dateien aus, oder irre ich mich.

Benmik 25. Dez 2017 20:44

AW: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von Hobby-Programmierer (Beitrag 1389651)
Zum Vergleich reicht doch das lesen der Dateien aus, oder irre ich mich.

???! Das müsstest du etwas ausführen. Bei ReadFile kommt der Windows File Cache ins Spiel, der durch
Delphi-Quellcode:
FILE_FLAG_NO_BUFFERING
umgangen wird.

Hobby-Programmierer 25. Dez 2017 21:04

AW: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Sorry @Benmik, kleines Missverständnis.
Ich hatte auf LTE5 geantwortet, der etwas von 'hier fehlt ein WriteFile für HZiel' gemurmelt hatte ;)
Schade wenn Antworten gelöscht werden, so geht natürlich der Kontext für nachfolgende Leser komplett verloren.

Zu Deinem Problem kann ich leider nix beitragen

himitsu 1. Jan 2018 14:13

AW: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Zitat:

Zitat von Benmik (Beitrag 1389648)
Ich frage mich aber, ist das eigentlich sinnvoll, den Cache hier zu umgehen? In meinem Szenario werden die Dateien nicht nochmal eingelesen, der Cache würde also keinen Vorteil bringen.

Es kommt darauf an wann die Dateien mehrmals gelesen werden, wenn zwischendurch der FileCache übergelaufen ist und der letzte Leseversuch schon weg ist, dann bringt der FileCache es absolut garnichts, außer dass durchs Auslagern deines und der anderen Programme alles Andere langamer wird.

Also ohne Cache ist es "meißtens" besser und du mußt das durch optimieren der restlichen Funktionen verbessern,
Also muß eine Datei wirklich mehrmals komplett gelesen werden? (z.B. erstmal Haschen und für den Erstvergleich zweier Dateien erstmal die Hashs verwenden, anstatt jedesmal wieder auf den Dateiinhalt zuzugreifen)

PS: Die Dateisystemtreiber arbeiten mit 64 KB als Transferpuffer (rate mal warum im Speicher zufällig der erste Speicherblok von $00000000 bis $0000FFFF gespert ist und wofür der z.B. verwendet wird).
Ja, Nonbuffered muß man mit dem Mehrfachen der Sektorgröße abeiten, da nur komplette Sektoren gelesen und vorallem geschrieben werden können. Und um die IOPs zu optimieren nimmt man dann ein Mehrfaches sämtlicher durchlaufener Puffer/Caches.

Hier im Forum suchenSearchSameFiles :stupid:

Benmik 2. Jan 2018 13:10

AW: Datei kopieren ohne Cache (FILE_FLAG_NO_BUFFERING)
 
Hallo himitsu, vielen Dank. Dann scheint das alles doch in die richtige Richtung zu gehen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:24 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