WriteFile-Funktion (fileapi.h)
Schreibt Daten in die angegebene Datei oder eingabe/ausgabe (E/A)-Gerät.
Diese Funktion ist sowohl für synchrone als auch für asynchrone Vorgänge konzipiert. Eine ähnliche Funktion, die ausschließlich für asynchronen Vorgang 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. datei, Dateidatenstrom, physischer Datenträger, Volume, Konsolenpuffer, Bandlaufwerk, Socket, Kommunikationsressource, Mailslot oder Pipe).
Der hFile- Parameter muss mit dem Schreibzugriff erstellt worden sein. Weitere Informationen finden Sie unter Generic Access Rights und File Security and Access Rights.
Bei asynchronen Schreibvorgängen können hFile- ein beliebiges Handle sein, das mit der CreateFile--Funktion mithilfe des FILE_FLAG_OVERLAPPED Flags oder eines Sockethandles geöffnet wird, das vom Socket- oder Funktion 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.
Ein Wert von Null gibt einen Null-Schreibvorgang an. Das Verhalten eines Null-Schreibvorgangs hängt von dem zugrunde liegenden Dateisystem oder der Kommunikationstechnologie ab.
Windows Server 2003 und Windows XP: Pipe-Schreibvorgänge in einem Netzwerk sind pro Schreibzugriff begrenzt. Der Betrag variiert je Nach Plattform. Für x86-Plattformen beträgt dies 63,97 MB. Für x64-Plattformen beträgt dies 31,97 MB. Für Itanium beträgt 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 Bytes empfängt, die bei Verwendung eines synchronen hFile--Parameters geschrieben wurden. 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- werden, wenn der parameter lpOverlap ped nicht NULL-ist.
Windows 7: Dieser Parameter kann nicht NULL-werden.
Weitere Informationen finden Sie im Abschnitt "Hinweise".
[in, out, optional] lpOverlapped
Ein Zeiger auf eine OVERLAPPED--Struktur ist erforderlich, wenn der hFile-Parameter mit FILE_FLAG_OVERLAPPEDgeöffnet wurde, andernfalls kann dieser Parameter NULL-sein.
Für eine hFile-, die Byte-Offsets unterstützt, müssen Sie bei Verwendung dieses Parameters einen Byte-Offset angeben, bei dem mit dem Schreiben in die Datei oder das Gerät begonnen werden soll. Dieser Offset wird durch Festlegen des Offset- und OffsetHigh Member der OVERLAPPED-Struktur angegeben. Bei einer hFile-, die Byteoffsets nicht unterstützt, werden Offset- und OffsetHigh- ignoriert.
Um in das Ende der Datei zu schreiben, geben Sie sowohl die Offset- als auch OffsetHigh Member der OVERLAPPED Struktur als 0xFFFFFFFF an. Dies entspricht funktional dem aufrufen der CreateFile--Funktion, um hFile- mit FILE_APPEND_DATA Zugriff zu öffnen.
Weitere Informationen zu verschiedenen Kombinationen von lpOverlapped und FILE_FLAG_OVERLAPPEDfinden 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 null (FALSE). Rufen Sie zum Abrufen erweiterter Fehlerinformationen die GetLastError--Funktion auf.
Bemerkungen
Die WriteFile--Funktion gibt zurück, wenn eine der folgenden Bedingungen auftritt:
- Die Anzahl der angeforderten Bytes wird geschrieben.
- Ein Lesevorgang gibt Pufferraum am Leseende der Pipe frei (wenn der Schreibvorgang blockiert wurde). Weitere Informationen finden Sie im Abschnitt Pipes.
- Ein asynchrones Handle wird verwendet, und der Schreibvorgang erfolgt asynchron.
- Ein Fehler tritt auf.
Um alle ausstehenden asynchronen E/A-Vorgänge abzubrechen, verwenden Sie eine der folgenden Aktionen:
- CancelIo– diese Funktion bricht nur Vorgänge ab, die vom aufrufenden Thread für das angegebene Dateihandle ausgegeben werden.
- CancelIoEx-– diese Funktion bricht alle Vorgänge ab, die von den Threads für das angegebene Dateihandle ausgegeben werden.
E/A-Vorgänge, die mit dem Fehler ERROR_OPERATION_ABORTEDabgebrochen werden.
Die WriteFile--Funktion kann mit ERROR_NOT_ENOUGH_QUOTAfehlschlagen, was bedeutet, dass der Puffer des aufrufenden Prozesses nicht seitensperrt sein konnte. Weitere Informationen finden Sie unter SetProcessWorkingSetSize.
Wenn ein Teil der Datei durch einen anderen Prozess gesperrt ist und der Schreibvorgang den gesperrten Teil überlappt, schlägt WriteFile- fehl.
Beim Schreiben in eine Datei wird die letzte Schreibzeit 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 sicherzustellen, dass die letzte Schreibzeit korrekt ist.
Der Zugriff auf den Ausgabepuffer, während ein Schreibvorgang den Puffer verwendet, kann zu Einer Beschädigung der daten führen, die aus diesem Puffer geschrieben wurden. Anwendungen dürfen nicht in den Ausgabepuffer schreiben, neu zuweisen oder freigeben, den ein Schreibvorgang verwendet, bis der Schreibvorgang abgeschlossen ist. Dies kann besonders problematisch sein, wenn sie ein asynchrones Dateihandle verwenden. Weitere Informationen zu synchronen und asynchronen Dateihandles finden Sie weiter unten im Abschnitt Synchronisierung und Dateiposition und Synchrone und asynchrone E/A-.
Beachten Sie, dass die Zeitstempel für eine Remotedatei möglicherweise nicht ordnungsgemäß aktualisiert werden. Um konsistente Ergebnisse sicherzustellen, verwenden Sie nicht gepufferte E/A.
Das System interpretiert Nullbytes, um zu schreiben, indem er einen Null-Schreibvorgang angibt, und WriteFile- die Datei nicht abschneidet oder erweitert. Verwenden Sie zum Abschneiden oder Erweitern einer Datei die SetEndOfFile-funktion.
Zeichen können mithilfe 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 an 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 und mithilfe der SetCommTimeouts- und GetCommTimeouts--Funktionen abgerufen. Unvorhersehbare Ergebnisse können auftreten, wenn Sie die Timeoutwerte nicht festlegen. Weitere Informationen zu Kommunikationstimeouts finden Sie unter COMMTIMEOUTS.
Obwohl ein Schreibvorgang in einem einzelnen Sektor atomisch ist, ist ein Multisektor-Schreibvorgang nicht garantiert atomisch, es sei denn, Sie verwenden eine Transaktion (d. r., der erstellte Handle ist ein Transaktionshandle, z. B. ein Handle, der mit CreateFileTransactederstellt wurde). Multi-Sector-Schreibvorgänge, 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 Mehrsektor-Schreibvorgang ohne potenzielle Zwischenspeicherungsverzögerungen auf den Datenträger geschrieben wird.
Wenn Sie direkt auf ein Volume schreiben, das über ein bereitgestelltes Dateisystem verfügt, müssen Sie zuerst exklusiven Zugriff auf das Volume erhalten. Andernfalls riskieren Sie Datenbeschädigungen oder Systeminstabilität, da die Schreibvorgänge Ihrer Anwendung möglicherweise mit anderen Änderungen aus dem Dateisystem in Konflikt treten und den Inhalt des Volumes in einem inkonsistenten Zustand belassen. Um diese Probleme zu vermeiden, wurden die folgenden Änderungen in Windows Vista und höher vorgenommen:
- Ein Schreibvorgang auf einem Volumehandle ist erfolgreich, wenn das Volume nicht über ein bereitgestelltes Dateisystem verfügt oder eine der folgenden Bedingungen zutrifft:
- Die zu schreibenden Sektoren sind Boot-Sektoren.
- Die Zu schreibenden Sektoren befinden sich außerhalb des Dateisystembereichs.
- Sie haben das Volume explizit gesperrt oder aufgehoben, indem Sie FSCTL_LOCK_VOLUME oder FSCTL_DISMOUNT_VOLUMEverwenden.
- Das Volume hat kein tatsächliches Dateisystem. (Mit anderen Worten, es ist ein RAW-Dateisystem bereitgestellt.)
- Ein Schreibvorgang auf einem Datenträgerhandle wird erfolgreich ausgeführt, wenn eine der folgenden Bedingungen zutrifft:
- Die zu schreibenden Sektoren fallen nicht in den Umfang eines Volumens.
- Die Sektoren, die in ein bereitgestelltes Volume fallen sollen, aber Sie haben das Volume explizit gesperrt oder aufgehoben, indem Sie FSCTL_LOCK_VOLUME oder FSCTL_DISMOUNT_VOLUMEverwenden.
- Die Sektoren, die geschrieben werden sollen, um in ein Volume zu fallen, das kein bereitgestelltes Dateisystem als RAW enthält.
Wenn hFile- mit FILE_FLAG_OVERLAPPEDgeöffnet wurde, sind die folgenden Bedingungen wirksam:
- Der parameter lpOverlapped muss auf eine gültige und eindeutige OVERLAPPED-Struktur verweisen, andernfalls kann die Funktion fälschlicherweise melden, dass der Schreibvorgang abgeschlossen ist.
- Der parameter lpNumberOfBytesWritten sollte auf NULL-festgelegt werden. Verwenden Sie zum Abrufen der Anzahl geschriebener Bytes die GetOverlappedResult--Funktion. Wenn der hFile- Parameter einem E/A-Vervollständigungsport zugeordnet ist, können Sie auch die Anzahl der Bytes abrufen, die durch Aufrufen der GetQueuedCompletionStatus--Funktion geschrieben wurden.
Technologie | Abgestützt |
---|---|
Server Message Block (SMB) 3.0-Protokoll | Ja |
SMB 3.0 Transparent Failover (TFO) | Ja |
SMB 3.0 mit Skalierungsdateifreigaben (SO) | Ja |
Freigegebenes Clustervolumedateisystem (CsvFS) | Ja |
Resilient File System (ReFS) | Ja |
Synchronisierung und Dateiposition
Wenn hFile- mit FILE_FLAG_OVERLAPPEDgeöffnet wird, handelt es sich um ein asynchrones Dateihandle; andernfalls ist sie synchron. Die Regeln für die Verwendung der OVERLAPPED Struktur unterscheiden sich geringfügig für jede Struktur, wie bereits erwähnt.- WriteFile- kann vor Abschluss des Schreibvorgangs zurückgegeben werden. In diesem Szenario gibt WriteFile-FALSE- zurück, und die GetLastError-Funktion gibt ERROR_IO_PENDINGzurück, wodurch der Aufrufvorgang fortgesetzt werden kann, während das System den Schreibvorgang abgeschlossen hat.
- Der parameter lpOverlapped darf nicht NULL- sein und sollte unter Berücksichtigung der folgenden Fakten verwendet werden:
- Obwohl das in der OVERLAPPED Struktur angegebene Ereignis vom System festgelegt und automatisch zurückgesetzt wird, wird der Offset, der in der OVERLAPPED Struktur angegeben ist, nicht automatisch aktualisiert.
- WriteFile setzt das Ereignis auf einen nicht signalfreien Zustand zurück, wenn der E/A-Vorgang beginnt.
- Das in der OVERLAPPED Struktur angegebene Ereignis wird auf einen signalisierten Zustand 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- zurückgibt, bevor der Schreibvorgang auf Systemebene abgeschlossen ist (schreibgeschützt), 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 abgeschlossen ist).
- Wenn lpOverlapped-NULL-ist, wird der Schreibvorgang an der aktuellen Dateiposition gestartet, und WriteFile- wird erst zurückgegeben, wenn der Vorgang abgeschlossen ist, und das System aktualisiert den Dateizeiger, bevor WriteFile- zurückgegeben wird.
- Wenn lpOverlapped- nicht NULL-ist, beginnt der Schreibvorgang beim Offset, der in der struktur OVERLAPPED angegeben ist, und WriteFile- erst zurückgegeben wird, wenn der Schreibvorgang abgeschlossen ist. Das System aktualisiert die felder OVERLAPPED Internal and InternalHigh fields und the file pointer before WriteFile returns.
Rohre
Wenn eine anonyme Pipe verwendet wird und der Lesehandle geschlossen wurde, wenn WriteFile- versucht, mithilfe des entsprechenden Schreibkästchens der Pfeife zu schreiben, gibt die Funktion FALSE- zurück und GetLastError gibt ERROR_BROKEN_PIPEzurück.Wenn der Pipepuffer voll ist, wenn eine Anwendung die WriteFile--Funktion zum Schreiben in eine Pipe verwendet, wird der Schreibvorgang möglicherweise nicht sofort beendet. Der Schreibvorgang wird abgeschlossen, wenn ein Lesevorgang (mithilfe der ReadFile--Funktion) mehr Systempufferplatz für die Pipe zur Verfügung stellt.
Beim Schreiben in ein nicht blockierendes Bytemodus-Pipehandle mit unzureichendem Pufferspeicher gibt WriteFile-TRUE- mit *lpNumberOfBytesWritten<nNumberOfBytesToWritezurück.
Weitere Informationen zu Rohren finden Sie unter Pipes.
Transacted Operations
Wenn eine Transaktion an das Dateihandle gebunden ist, wird der Dateischreibvorgang durchgeführt. Weitere Informationen finden Sie unter About Transactional NTFS.Beispiele
Einige Beispiele finden Sie unter Erstellen und Verwenden einer temporären Datei und Öffnen einer Datei zum Lesen oder Schreiben von.
Im folgenden C++-Beispiel wird gezeigt, wie Sektoren für nicht gepufferte Dateischreibvorgänge ausgerichtet werden. Die variable Größe ist die Größe des ursprünglichen Datenblocks, den Sie in die Datei schreiben möchten. Weitere Regeln für nicht entbufferte Datei-E/A 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
Anforderung | Wert |
---|---|
mindestens unterstützte Client- | Windows XP [Desktop-Apps | UWP-Apps] |
mindestens unterstützte Server- | Windows Server 2003 [Desktop-Apps | UWP-Apps] |
Zielplattform- | Fenster |
Header- | fileapi.h (include Windows.h) |
Library | Kernel32.lib |
DLL- | Kernel32.dll |