![]() |
Datei physikalisch lesen/schreiben ohne den Windows-Cache
Hallo,
ich muss auf einem USB-Stick eine Datei erstellen, ihren Inhalt lesen und anschließend miteinander vergleichen. Das habe ich bisher mit normalen Delphi-Funktionen realisiert (Assign, Rewrite, Write, Read, Close). Die Sache hat nur einen Haken: den Windows-Cache. Beim Schreiben auf den USB-Stick meldet mir Windows schneller, dass die Datei geschrieben wurde, als es tatsächlich der Fall ist. Somit kann ich nicht den Zeitpunkt ermitteln, bei dem ich mit dem Lesen beginnen kann. Um dieses Problem zu umgehen, habe ich gehört, man kann das entsprechende Medium physikalisch öffnen und somit am Windows-Cache "vorbeischreiben". Bisher habe ich physikalische Laufwerke immer so geöffnet:
Delphi-Quellcode:
und so
Handle := CreateFile(PChar('\\.\PhysicalDrive1'),
0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
Delphi-Quellcode:
wieder geschlossen.
CloseHandle(Handle);
Nun ist mir allerdings schleierhaft, wie ich nach dem Öffnen eine Datei schreiben soll. Es gibt zwar die WriteFile- und ReadFile-Funktionen, die nach dem Aufruf von CreateFile zum Einsatz kommen, aber wie soll ich da eine Datei angeben, die zuvor auch noch erstellt werden muss ? |
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Moin, Moin,
wie wäre es, wenn du statt OPEN_EXISTING mal CREATE_NEW verwendest (F1 auf CreateFile öffnet die recht gute Hilfe) ... Gruß Ralph :bounce1: |
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Zitat:
Lösung: einen Stream verwenden. Man kann aber nicht direkt einen TFileStream verwenden, sondern muss auf THandleStream ausweichen. Nur so kann man FILE_FLAG_WRITE_THROUGH angeben.
Delphi-Quellcode:
function CreateUnbuffedFilestream(const filename:string):TStream;
var fhandle : THandle; begin fhandle := CreateFile(PChar(filename), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_WRITE_THROUGH, 0); if hnd <> INVALID_HANDLE_VALUE then result := THandleStream.Create(fhandle) else result := nil; end; |
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Mal ne vielleicht doofe Frage:
Wenn ich eine Datei schreibe und die sofort danach wieder lesen will, kann es mir dann aus meiner (Anwender-)Sicht nicht egal sein, ob Caches verwendet werden oder nicht? Caches (zumindest die Schreibcaches bei Datenträgern) sollten transparent sein, es ist (in diesem Fall) Sache des Betriebssystems bzw. der Treiber, dafür zu sorgen. Wenn ich also eine Datei schreibe und diese dann nicht sofort lesen kann, so ist das meiner Meinung nach ein Mangel des Betriebssystems, der behoben werden sollte. Oder versteh ich da was falsch? |
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Ich glaub sein Problem ist, das Windows Erfolf meldet, die daten aber noch nicht zurückgeschrieben wurden. wenn man nun den Stick abzieht, hat man Müll!
|
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Ach so! Gut, das wäre eine Erklärung.
Dann würde ich aber sagen, er sollte lieber prüfen, ob der Stick abgezogen werden kann oder nicht. Dafür ist ja das Dienstprogramm von Windows da, das sich in der Systray einnistet. Wenn man die gleiche Prüfung, die in diesem Programm vorkommt, anwendet, sollte das gewünschte erreicht sein. Bleibt natürlich die Frage, welche das genau ist ;-) Ich finds eben unsauber, ganz auf den Schreibcache zu verzichten. Wenn der Administrator des Systems den Schreibcache anschaltet, dann wird er sich was dabei denken und fände es nicht schön, wenn jedes Programm diese Einstellung ignoriert und durchschreibt. Dann kann er den Cache auch gleich deaktivieren. Das soll jetzt keine generelle Kritik an der Vorangehensweise sein, ich weiß ja nicht, was das Programm konkret machen soll. Aber prinzipiell finde ich, man sollte zunächst mal versuchen, mit der Konfiguration des Betriebssystem zurechtzukommen, als diese umgehen zu wollen. |
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Dieses Fehlverhalten bei Wechseldatenträgern hatte Windows nur bei 2000. Bei XP ist der Schreibcache bei Wechseldatenträgern standardmässig deaktiviert. Grundlegend weiss man aber trotzdem nicht, wann er mit dem Schreiben fertig ist, so lange man nicht mit der WebCam die LED des Sticks beobachtet :zwinker:
|
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Vielleicht war die gewünschte Aufgabe meiner Anwendung falsch umschrieben.
Eine Teilapplikation soll bspw. die Lesegeschwindigkeit der USB-Medien und auch einer zuvor gebrannten CD ermitteln. Dafür wird die Testdatei eingelesen und die Zeit ermittelt, die dafür benötigt wird. Nehmen wir einmal an, dieser Vorgang dauert für eine 16 MByte Datei 5 Sekunden. Beim zweiten Einlesevorgang nimmt Windows die Datei aber aus seinem Datei-Cache und ich erhalte eine Lesezeit von 0,01 Sekunden - das verfälscht mein Ergebnis auf unerwünschte Art und Weise. Wenn die CreateFile-Methode bedeutet, dass ich mich mit Dateisystemen und Sektoren rumschlagen muss, ist die Sache den Aufwand nicht Wert. Mir ist auch keine Windows API-Funktion bekannt, um den Dateisystemcache für bestimmte Laufwerke abzuschalten (was allerdings ohne Neustart erfolgen müsste). @shmia: Deinen Vorschlag mit dem Stream muss ich ausprobieren, er klingt auch recht vielversprechend. Info folgt dann hier in dieser Diskussion. |
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Zitat:
ich muss nochmal auf Deinen oben genannten Code zurückkommen. Zuerst einmal funktioniert er. Ist es aber möglich, dass das Beschreiben mit FILE_FLAG_WRITE_THROUGH fast 20mal so lange benötigt als ohne? Ich schreibe etwa eine 1 MByte Testdatei auf einen USB-Stick und das braucht fast 2 Minuten mit FILE_FLAG_WRITE_THROUGH, ohne nur wenige Sekunden. Wenn ich FILE_FLAG_NO_BUFFERING anstatt von FILE_FLAG_WRITE_THROUGH verwende, erhalte ich beim ersten Aufruf von WriteBuffer eine Exception 'Stream-Schreibfehler'. Es geht mir ja darum, Daten ohne den Windows-Cache zu schreiben. Bei der benötigten Zeit mit FILE_FLAG_WRITE_THROUGH darf ich mir garnicht vorstellen, wie lange eine 100 MByte Datei dauert. |
Re: Datei physikalisch lesen/schreiben ohne den Windows-Cach
Lass doch den Cache seine Arbeit machen.
Wenn die Datei geschrieben wurde, dann kann man ja ![]()
Delphi-Quellcode:
Bei einem USB-Stick kann es sein, dass dein Programm sekundenlang in FlushFileBuffers festhängt, weil es die Daten auf das physische Medium schreibt.
stream := TFileStream.Create(....
try // hier 100MB schreiben FlushFileBuffers(stream.Handle); // jetzt ist die Datei sicher auf dem Datenträger finally stream.Free; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:30 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