WriteFile-Funktion (fileapi.h)

Schreibt Daten in die angegebene Datei oder auf das angegebene Eingabe-/Ausgabegerät (E/A).

Diese Funktion ist sowohl für synchrone als auch für asynchrone Vorgänge konzipiert. Eine ähnliche Funktion, die ausschließlich für asynchrone Vorgänge entwickelt wurde, finden Sie unter WriteFileEx.

Syntax

BOOL WriteFile(
  [in]                HANDLE       hFile,
  [in]                LPCVOID      lpBuffer,
  [in]                DWORD        nNumberOfBytesToWrite,
  [out, optional]     LPDWORD      lpNumberOfBytesWritten,
  [in, out, optional] LPOVERLAPPED lpOverlapped
);

Parameter

[in] hFile

Ein Handle für die Datei oder das E/A-Gerät (z. B. eine Datei, einen Dateistream, einen physischen Datenträger, ein Volume, einen Konsolenpuffer, ein Bandlaufwerk, einen Socket, eine Kommunikationsressource, ein Maillot oder eine Pipe).

Der hFile-Parameter muss mit dem Schreibzugriff erstellt worden sein. Weitere Informationen finden Sie unter Generische Zugriffsrechte und Dateisicherheit und Zugriffsrechte.

Bei asynchronen Schreibvorgängen kann hFile ein beliebiges Handle sein, das mit der CreateFile-Funktion mit dem flag FILE_FLAG_OVERLAPPED oder einem Sockethandle geöffnet wird, das von der Socket- oder Acceptfunktion zurückgegeben wird.

[in] lpBuffer

Ein Zeiger auf den Puffer, der die Daten enthält, die in die Datei oder das Gerät geschrieben werden sollen.

Dieser Puffer muss für die Dauer des Schreibvorgangs gültig bleiben. Der Aufrufer darf diesen Puffer erst verwenden, wenn der Schreibvorgang abgeschlossen ist.

[in] nNumberOfBytesToWrite

Die Anzahl der Bytes, die in die Datei oder das Gerät geschrieben werden sollen.

Der Wert 0 (null) gibt einen NULL-Schreibvorgang an. Das Verhalten eines NULL-Schreibvorgangs hängt vom zugrunde liegenden Dateisystem oder der zugrunde liegenden Kommunikationstechnologie ab.

Windows Server 2003 und Windows XP: Pipeschreibvorgänge in einem Netzwerk sind in der Größe pro Schreibvorgang begrenzt. Der Betrag variiert je nach Plattform. Bei x86-Plattformen beträgt dies 63,97 MB. Bei x64-Plattformen sind es 31,97 MB. Für Itanium sind es 63,95 MB. Weitere Informationen zu Rohren finden Sie im Abschnitt Hinweise.

[out, optional] lpNumberOfBytesWritten

Ein Zeiger auf die Variable, die die Anzahl der geschriebenen Bytes empfängt, wenn ein synchroner hFile-Parameter verwendet wird. WriteFile legt diesen Wert vor der Arbeit oder Fehlerüberprüfung auf Null fest. Verwenden Sie NULL für diesen Parameter, wenn es sich um einen asynchronen Vorgang handelt, um potenziell fehlerhafte Ergebnisse zu vermeiden.

Dieser Parameter kann nur NULL sein, wenn der lpOverlapped-Parameter nicht NULL ist.

Windows 7: Dieser Parameter darf nicht NULL sein.

Weitere Informationen finden Sie im Abschnitt mit Hinweisen.

[in, out, optional] lpOverlapped

Ein Zeiger auf eine OVERLAPPED-Struktur ist erforderlich, wenn der hFile-Parameter mit FILE_FLAG_OVERLAPPED geöffnet wurde. Andernfalls kann dieser Parameter NULL sein.

Wenn Sie diesen Parameter für eine hFile-Datei verwenden, die Byteoffsets unterstützt, müssen Sie einen Byteoffset angeben, an dem mit dem Schreiben in die Datei oder das Gerät begonnen werden soll. Dieser Offset wird durch Festlegen der Offset - und OffsetHigh-Elemente der OVERLAPPED-Struktur angegeben. Bei einer hFile-Datei , die byteoffsets nicht unterstützt, werden Offset und OffsetHigh ignoriert.

Um an das Ende der Datei zu schreiben, geben Sie sowohl die Offset - als auch die OffsetHigh-Member der OVERLAPPED-Struktur als 0xFFFFFFFF an. Dies entspricht funktional dem Aufruf der CreateFile-Funktion , um hFile mit FILE_APPEND_DATA Zugriff zu öffnen.

Weitere Informationen zu verschiedenen Kombinationen von lpOverlapped und FILE_FLAG_OVERLAPPED finden Sie im Abschnitt Hinweise und im Abschnitt Synchronisierung und Dateiposition .

Rückgabewert

Wenn die Funktion erfolgreich ist, ist der Rückgabewert ungleich null (TRUE).

Wenn die Funktion fehlschlägt oder asynchron abgeschlossen wird, ist der Rückgabewert 0 (FALSE). Um erweiterte Fehlerinformationen zu erhalten, rufen Sie die GetLastError-Funktion auf.

Hinweis Der GetLastError-CodeERROR_IO_PENDING ist kein Fehler. Er legt fest, dass der Schreibvorgang asynchron abgeschlossen wird. Weitere Informationen finden Sie in den Hinweisen.
 

Hinweise

Die WriteFile-Funktion gibt zurück, wenn eine der folgenden Bedingungen auftritt:

  • Die Anzahl der angeforderten Bytes wird geschrieben.
  • Bei einem Lesevorgang wird Pufferspeicherplatz am Leseende der Pipe freigegeben (wenn der Schreibvorgang blockiert wurde). Weitere Informationen finden Sie im Abschnitt Pipes .
  • Es wird ein asynchrones Handle verwendet, und der Schreibvorgang erfolgt asynchron.
  • Ein Fehler tritt auf.
Die WriteFile-Funktion schlägt möglicherweise mit ERROR_INVALID_USER_BUFFER oder ERROR_NOT_ENOUGH_MEMORY fehl, wenn zu viele asynchrone E/A-Anforderungen ausstehen.

Verwenden Sie eine der folgenden Optionen, um alle ausstehenden asynchronen E/A-Vorgänge abzubrechen:

  • CancelIo: Diese Funktion bricht nur Vorgänge ab, die vom aufrufenden Thread für das angegebene Dateihandle ausgegeben wurden.
  • CancelIoEx: Diese Funktion bricht alle Vorgänge ab, die von den Threads für das angegebene Dateihandle ausgegeben wurden.
Verwenden Sie die CancelSynchronousIo-Funktion , um ausstehende synchrone E/A-Vorgänge abzubrechen.

E/A-Vorgänge, die mit dem fehler ERROR_OPERATION_ABORTED abgebrochen werden.

Die WriteFile-Funktion schlägt möglicherweise mit ERROR_NOT_ENOUGH_QUOTA fehl, was bedeutet, dass der Puffer des aufrufenden Prozesses nicht seitengesperrt sein konnte. Weitere Informationen finden Sie unter SetProcessWorkingSetSize.

Wenn ein Teil der Datei von einem anderen Prozess gesperrt wird und der Schreibvorgang den gesperrten Teil überlappt, schlägt WriteFile fehl.

Beim Schreiben in eine Datei wird der Zeitpunkt des letzten Schreibvorgangs erst vollständig aktualisiert, wenn alle zum Schreiben verwendeten Handles geschlossen wurden. Schließen Sie daher das Dateihandle unmittelbar nach dem Schreiben in die Datei, um eine genaue letzte Schreibzeit sicherzustellen.

Der Zugriff auf den Ausgabepuffer, während ein Schreibvorgang den Puffer verwendet, kann zu einer Beschädigung der aus diesem Puffer geschriebenen Daten führen. Anwendungen dürfen den Ausgabepuffer, den ein Schreibvorgang verwendet, nicht in schreiben, neu zuweisen oder freigeben, bis der Schreibvorgang abgeschlossen ist. Dies kann besonders problematisch sein, wenn ein asynchrones Dateihandle verwendet wird. Weitere Informationen zu synchronen und asynchronen Dateihandles finden Sie später im Abschnitt Synchronisierung und Dateiposition sowie synchrone und asynchrone E/A.

Beachten Sie, dass die Zeitstempel für eine Remotedatei möglicherweise nicht ordnungsgemäß aktualisiert werden. Um konsistente Ergebnisse zu gewährleisten, verwenden Sie ungepufferte E/A-Vorgänge.

Das System interpretiert null bytes to write so, dass ein NULL-Schreibvorgang angegeben wird, und WriteFile schneidet die Datei nicht ab oder erweitert sie nicht. Verwenden Sie zum Abschneiden oder Erweitern einer Datei die SetEndOfFile-Funktion .

Zeichen können mithilfe von WriteFile mit einem Handle für die Konsolenausgabe in den Bildschirmpuffer geschrieben werden. Das genaue Verhalten der Funktion wird durch den Konsolenmodus bestimmt. Die Daten werden in die aktuelle Cursorposition geschrieben. Die Cursorposition wird nach dem Schreibvorgang aktualisiert. Weitere Informationen zu Konsolenhandles finden Sie unter CreateFile.

Beim Schreiben auf ein Kommunikationsgerät wird das Verhalten von WriteFile durch das aktuelle Kommunikationstimeout bestimmt, wie festgelegt und mithilfe der Funktionen SetCommTimeouts und GetCommTimeouts abgerufen. Unvorhersehbare Ergebnisse können auftreten, wenn Sie die Timeoutwerte nicht festlegen können. Weitere Informationen zu Kommunikationstimeouts finden Sie unter COMMTIMEOUTS.

Obwohl ein Schreibvorgang mit einem einzelnen Sektor atomar ist, ist ein Schreibvorgang mit mehreren Sektoren nicht garantiert unteilbar, es sei denn, Sie verwenden eine Transaktion (d. a. das erstellte Handle ist ein Transaktionshandle, z. B. ein mit CreateFileTransacted erstelltes Handle). Schreibvorgänge mit mehreren Sektoren, die zwischengespeichert werden, werden möglicherweise nicht immer sofort auf den Datenträger geschrieben. Geben Sie daher FILE_FLAG_WRITE_THROUGH in CreateFile an, um sicherzustellen, dass ein vollständiger Multisektorenschreibvorgang ohne potenzielle Zwischenspeicherungsverzögerungen auf den Datenträger geschrieben wird.

Wenn Sie direkt auf ein Volume schreiben, das über ein eingebundenes Dateisystem verfügt, müssen Sie zunächst exklusiven Zugriff auf das Volume erhalten. Andernfalls besteht das Risiko einer Datenbeschädigung oder Systeminstabilität, da die Schreibvorgänge Ihrer Anwendung mit anderen Änderungen aus dem Dateisystem in Konflikt stehen und den Inhalt des Volumes in einem inkonsistenten Zustand belassen können. Um diese Probleme zu vermeiden, wurden die folgenden Änderungen in Windows Vista und höher vorgenommen:

  • Ein Schreibvorgang auf ein Volumehandle ist erfolgreich, wenn das Volume kein eingebundenes Dateisystem aufweist oder eine der folgenden Bedingungen zutrifft:
    • Die Sektoren, in die geschrieben werden soll, sind Startsektoren.
    • Die Sektoren, die geschrieben werden sollen, um sich außerhalb des Dateisystembereichs zu befinden.
    • Sie haben die Bereitstellung des Volumes mithilfe von FSCTL_LOCK_VOLUME oder FSCTL_DISMOUNT_VOLUME explizit gesperrt oder aufgehoben.
    • Das Volume verfügt über kein tatsächliches Dateisystem. (Mit anderen Worten, es ist ein RAW-Dateisystem eingebunden.)
  • Ein Schreibvorgang auf ein Datenträgerhandle ist erfolgreich, wenn eine der folgenden Bedingungen zutrifft:
    • Die Sektoren, in die geschrieben werden soll, liegen nicht in den Umfang eines Volumes.
    • Die Sektoren, die geschrieben werden sollen, um in ein eingebundenes Volume zu fallen, Aber Sie haben die Bereitstellung des Volumes mithilfe von FSCTL_LOCK_VOLUME oder FSCTL_DISMOUNT_VOLUME explizit gesperrt oder aufgehoben.
    • Die Zu schreibenden Sektoren gehören zu einem Volume, das außer RAW über kein eingebundenes Dateisystem verfügt.
Es gibt strenge Anforderungen für die erfolgreiche Arbeit mit Dateien, die mit CreateFile mithilfe von FILE_FLAG_NO_BUFFERING geöffnet wurden. Weitere Informationen finden Sie unter Dateipufferung.

Wenn hFile mit FILE_FLAG_OVERLAPPED geöffnet wurde, gelten die folgenden Bedingungen:

  • Der lpOverlapped-Parameter muss auf eine gültige und eindeutige OVERLAPPED-Struktur verweisen, andernfalls kann die Funktion fälschlicherweise melden, dass der Schreibvorgang abgeschlossen ist.
  • Der lpNumberOfBytesWritten-Parameter sollte auf NULL festgelegt werden. Verwenden Sie die GetOverlappedResult-Funktion , um die Anzahl der geschriebenen Bytes abzurufen. Wenn der hFile-Parameter einem E/A-Abschlussport zugeordnet ist, können Sie auch die Anzahl der geschriebenen Bytes abrufen, indem Sie die GetQueuedCompletionStatus-Funktion aufrufen.
In Windows Server 2012 wird diese Funktion von den folgenden Technologien unterstützt.
Technologie Unterstützt
SMB 3.0-Protokoll (Server Message Block) Ja
SMB 3.0 Transparent Failover (TFO) Ja
SMB 3.0 mit Dateifreigaben mit horizontaler Skalierung (SO) Ja
Dateisystem mit freigegebenen Clustervolumes (CsvFS) Ja
Robustes Dateisystem (Resilient File System, ReFS) Ja
 

Synchronisierung und Dateiposition

Wenn hFile mit FILE_FLAG_OVERLAPPED geöffnet wird, handelt es sich um ein asynchrones Dateihandle. andernfalls ist es synchron. Wie bereits erwähnt, unterscheiden sich die Regeln für die Verwendung der OVERLAPPED-Struktur geringfügig.
Hinweis Wenn eine Datei oder ein Gerät für asynchrone E/A geöffnet wird, werden nachfolgende Aufrufe von Funktionen wie WriteFile mit diesem Handle in der Regel sofort zurückgegeben, können sich aber auch synchron in Bezug auf blockierte Ausführung verhalten. Weitere Informationen finden Sie unter http://support.microsoft.com/kb/156932.
 
Überlegungen zum Arbeiten mit asynchronen Dateihandles:
  • WriteFile kann zurückgegeben werden, bevor der Schreibvorgang abgeschlossen ist. In diesem Szenario gibt WriteFileFALSE zurück, und die GetLastError-Funktion gibt ERROR_IO_PENDING zurück, sodass der aufrufende Prozess fortgesetzt werden kann, während das System den Schreibvorgang abgeschlossen hat.
  • Der lpOverlapped-Parameter darf nicht NULL sein und sollte unter Berücksichtigung der folgenden Fakten verwendet werden:
    • Obwohl das in der OVERLAPPED-Struktur angegebene Ereignis vom System automatisch festgelegt und zurückgesetzt wird, wird der in der OVERLAPPED-Struktur angegebene Offset nicht automatisch aktualisiert.
    • WriteFile setzt das Ereignis auf einen nicht signalierten Zustand zurück, wenn der E/A-Vorgang gestartet wird.
    • Das in der OVERLAPPED-Struktur angegebene Ereignis wird auf einen Signalzustand festgelegt, wenn der Schreibvorgang abgeschlossen ist. bis zu diesem Zeitpunkt gilt der Schreibvorgang als ausstehend.
    • Da der Schreibvorgang mit dem Offset beginnt, der in der OVERLAPPED-Struktur angegeben ist, und WriteFile möglicherweise zurückgegeben wird, bevor der Schreibvorgang auf Systemebene abgeschlossen ist (Schreibvorgang aussteht), sollte weder der Offset noch ein anderer Teil der Struktur von der Anwendung geändert, freigegeben oder wiederverwendet werden, bis das Ereignis signalisiert wird (d. h. der Schreibvorgang ist abgeschlossen).
Überlegungen zum Arbeiten mit synchronen Dateihandles:
  • Wenn lpOverlappedNULL ist, beginnt der Schreibvorgang an der aktuellen Dateiposition, und WriteFile wird erst zurückgegeben, wenn der Vorgang abgeschlossen ist, und das System aktualisiert den Dateizeiger, bevor WriteFile zurückgibt.
  • Wenn lpOverlapped nicht NULL ist, beginnt der Schreibvorgang am Offset, der in der OVERLAPPED-Struktur angegeben ist, und WriteFile wird erst zurückgegeben, wenn der Schreibvorgang abgeschlossen ist. Das System aktualisiert die Felder OVERLAPPED Internal und InternalHigh sowie den Dateizeiger, bevor WriteFile zurückgibt.
Weitere Informationen finden Sie unter CreateFile und Synchrone und asynchrone E/A.

Rohre

Wenn eine anonyme Pipe verwendet wird und das Lesehandle geschlossen wurde, gibt die Funktion false und GetLastErrorERROR_BROKEN_PIPE zurück, wenn WriteFile versucht, mit dem entsprechenden Schreibhandle der Pipe zu schreiben.

Wenn der Pipepuffer voll ist, wenn eine Anwendung die WriteFile-Funktion verwendet, um in eine Pipe zu schreiben, wird der Schreibvorgang möglicherweise nicht sofort abgeschlossen. Der Schreibvorgang wird abgeschlossen, wenn ein Lesevorgang (mithilfe der ReadFile-Funktion ) mehr Systempufferspeicherplatz für die Pipe zur Verfügung stellt.

Beim Schreiben in ein nicht blockierendes Pipehandle im Bytemodus mit unzureichendem Pufferspeicher gibt WriteFileTRUE mit *lpNumberOfBytesWritten<nNumberOfBytesToWrite zurück.

Weitere Informationen zu Pipes finden Sie unter Pipes.

Transaktionen

Ist an das Dateihandle eine Transaktion gebunden, ist der Dateischreibvorgang transaktiv. Weitere Informationen finden Sie unter Informationen zu Transaktions-NTFS.

Beispiele

Einige Beispiele finden Sie unter Erstellen und Verwenden einer temporären Datei und Öffnen einer Datei zum Lesen oder Schreiben.

Das folgende C++-Beispiel zeigt, wie Sektoren für nicht gepufferte Dateischreibvorgänge ausgerichtet werden. Die Größenvariable ist die Größe des ursprünglichen Datenblocks, den Sie in die Datei schreiben möchten. Weitere Regeln für nicht gepufferte E/A-Dateien finden Sie unter Dateipufferung.
#include <windows.h>

#define ROUND_UP_SIZE(Value,Pow2) ((SIZE_T) ((((ULONG)(Value)) + (Pow2) - 1) & (~(((LONG)(Pow2)) - 1))))

#define ROUND_UP_PTR(Ptr,Pow2)  ((void *) ((((ULONG_PTR)(Ptr)) + (Pow2) - 1) & (~(((LONG_PTR)(Pow2)) - 1))))

int main()
{
   // Sample data
   unsigned long bytesPerSector = 65536; // obtained from the GetFreeDiskSpace function.
   unsigned long size = 15536; // Buffer size of your data to write.
   
   // Ensure you have one more sector than Size would require.
   size_t sizeNeeded = bytesPerSector + ROUND_UP_SIZE(size, bytesPerSector);
   
   // Replace this statement with any allocation routine.
   auto buffer = new uint8_t[SizeNeeded];
   
   // Actual alignment happens here.
   auto bufferAligned = ROUND_UP_PTR(buffer, bytesPerSector);

   // ... Add code using bufferAligned here.
   
   // Replace with corresponding free routine.
   delete buffer;
}

Anforderungen

   
Unterstützte Mindestversion (Client) Windows XP [Desktop-Apps | UWP-Apps]
Unterstützte Mindestversion (Server) Windows Server 2003 [Desktop-Apps | UWP-Apps]
Zielplattform Windows
Kopfzeile fileapi.h (Einschließen von Windows.h)
Bibliothek Kernel32.lib
DLL Kernel32.dll

Siehe auch

CancelIo

CancelIoEx

CancelSynchronousIo

CreateFile

CreateFileTransacted

Dateiverwaltungsfunktionen

GetLastError

GetOverlappedResult

GetQueuedCompletionStatus

ReadFile

SetEndOfFile

WriteFileEx