Partager via


Fonction WriteFile (fileapi.h)

Écrit les données dans le fichier ou le périphérique d’entrée/sortie (E/S) spécifié.

Cette fonction est conçue pour les opérations synchrones et asynchrones. Pour une fonction similaire conçue uniquement pour une opération asynchrone, consultez WriteFileEx.

Syntaxe

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

Paramètres

[in] hFile

Handle pour le fichier ou l’appareil d’E/S (par exemple, un fichier, un flux de fichiers, un disque physique, un volume, une mémoire tampon de console, un lecteur de bande, un socket, une ressource de communication, un maillot ou un canal).

Le paramètre hFile doit avoir été créé avec l’accès en écriture. Pour plus d’informations, consultez Droits d’accès génériques et Sécurité des fichiers et Droits d’accès.

Pour les opérations d’écriture asynchrones, hFile peut être n’importe quel handle ouvert avec la fonction CreateFile à l’aide de l’indicateur FILE_FLAG_OVERLAPPED ou d’un handle de socket retourné par le socket ou la fonction accept .

[in] lpBuffer

Pointeur vers la mémoire tampon contenant les données à écrire dans le fichier ou l’appareil.

Cette mémoire tampon doit rester valide pendant la durée de l’opération d’écriture. L’appelant ne doit pas utiliser cette mémoire tampon tant que l’opération d’écriture n’est pas terminée.

[in] nNumberOfBytesToWrite

Nombre d’octets à écrire dans le fichier ou l’appareil.

La valeur zéro spécifie une opération d’écriture null. Le comportement d’une opération d’écriture null dépend du système de fichiers sous-jacent ou de la technologie de communication.

Windows Server 2003 et Windows XP : Les opérations d’écriture de canal sur un réseau sont limitées en taille par écriture. Le montant varie selon la plateforme. Pour les plateformes x86, elle est de 63,97 Mo. Pour les plateformes x64, il est de 31,97 Mo. Pour Itanium, il est de 63,95 Mo. Pour plus d’informations sur les tuyaux, consultez la section Remarques.

[out, optional] lpNumberOfBytesWritten

Pointeur vers la variable qui reçoit le nombre d’octets écrits lors de l’utilisation d’un paramètre hFile synchrone. WriteFile définit cette valeur sur zéro avant d’effectuer une vérification de travail ou d’erreur. Utilisez NULL pour ce paramètre s’il s’agit d’une opération asynchrone afin d’éviter des résultats potentiellement erronés.

Ce paramètre peut avoir la valeur NULL uniquement lorsque le paramètre lpOverlapped n’est pas NULL.

Windows 7 : Ce paramètre ne peut pas être NULL.

Pour plus d'informations, consultez la section Notes.

[in, out, optional] lpOverlapped

Un pointeur vers une structure OVERLAPPED est nécessaire si le paramètre hFile a été ouvert avec FILE_FLAG_OVERLAPPED, sinon ce paramètre peut être NULL.

Pour un fichier hFile qui prend en charge les décalages d’octets, si vous utilisez ce paramètre, vous devez spécifier un décalage d’octets à partir duquel commencer l’écriture dans le fichier ou l’appareil. Ce décalage est spécifié en définissant les membres Offset et OffsetHigh de la structure OVERLAPPED . Pour un fichier hFile qui ne prend pas en charge les décalages d’octets, Offset et OffsetHigh sont ignorés.

Pour écrire à la fin du fichier, spécifiez les membres Offset et OffsetHigh de la structure OVERLAPPED comme 0xFFFFFFFF. Sur le plan fonctionnel, cela équivaut à appeler précédemment la fonction CreateFile pour ouvrir hFile à l’aide d’un accès FILE_APPEND_DATA .

Pour plus d’informations sur les différentes combinaisons de lpOverlapped et de FILE_FLAG_OVERLAPPED, consultez la section Remarques et la section Synchronisation et position du fichier .

Valeur retournée

Si la fonction réussit, la valeur de retour est différente de zéro (TRUE).

Si la fonction échoue ou s’exécute de manière asynchrone, la valeur de retour est zéro (FALSE). Pour obtenir des informations détaillées sur l’erreur, appelez la fonction GetLastError.

Note Le code GetLastErrorERROR_IO_PENDING n’est pas un échec ; elle indique que l’opération d’écriture est en attente d’achèvement de façon asynchrone. Pour plus d'informations, consultez la section Notes.
 

Notes

La fonction WriteFile retourne l’une des conditions suivantes :

  • Le nombre d’octets demandés est écrit.
  • Une opération de lecture libère de l’espace tampon à l’extrémité de lecture du canal (si l’écriture a été bloquée). Pour plus d’informations, consultez la section Canaux .
  • Un handle asynchrone est utilisé et l’écriture se produit de manière asynchrone.
  • Une erreur se produit.
La fonction WriteFile peut échouer avec ERROR_INVALID_USER_BUFFER ou ERROR_NOT_ENOUGH_MEMORY chaque fois qu’il y a trop de demandes d’E/S asynchrones en attente.

Pour annuler toutes les opérations d’E/S asynchrones en attente, utilisez l’une des fonctions suivantes :

  • CancelIo : cette fonction annule uniquement les opérations émises par le thread appelant pour le handle de fichier spécifié.
  • CancelIoEx : cette fonction annule toutes les opérations émises par les threads pour le descripteur de fichier spécifié.
Utilisez la fonction CancelSynchronousIo pour annuler les opérations d’E/S synchrones en attente.

Les opérations d’E/S qui sont annulées sont terminées avec l’erreur ERROR_OPERATION_ABORTED.

La fonction WriteFile peut échouer avec ERROR_NOT_ENOUGH_QUOTA, ce qui signifie que la mémoire tampon du processus appelant n’a pas pu être verrouillée sur la page. Pour plus d’informations, consultez SetProcessWorkingSetSize.

Si une partie du fichier est verrouillée par un autre processus et que l’opération d’écriture chevauche la partie verrouillée, WriteFile échoue.

Lors de l’écriture dans un fichier, l’heure de la dernière écriture n’est pas entièrement mise à jour tant que tous les handles utilisés pour l’écriture n’ont pas été fermés. Par conséquent, pour garantir une heure exacte de la dernière écriture, fermez le handle de fichier immédiatement après l’écriture dans le fichier.

L’accès à la mémoire tampon de sortie pendant qu’une opération d’écriture utilise la mémoire tampon peut entraîner une altération des données écrites à partir de cette mémoire tampon. Les applications ne doivent pas écrire dans, réallouer ou libérer la mémoire tampon de sortie qu’une opération d’écriture utilise tant que l’opération d’écriture n’est pas terminée. Cela peut être particulièrement problématique lors de l’utilisation d’un handle de fichier asynchrone. Vous trouverez plus d’informations sur les descripteurs de fichiers synchrones et asynchrones plus loin dans la section Synchronisation et position du fichier et dans les E/S synchrones et asynchrones.

Notez que les horodatages peuvent ne pas être mis à jour correctement pour un fichier distant. Pour garantir des résultats cohérents, utilisez des E/S non déboguées.

Le système interprète zéro octet à écrire comme spécifiant une opération d’écriture null et WriteFile ne tronque pas le fichier ni ne l’étend. Pour tronquer ou étendre un fichier, utilisez la fonction SetEndOfFile .

Les caractères peuvent être écrits dans la mémoire tampon d’écran à l’aide de WriteFile avec un handle pour la sortie de la console. Le comportement exact de la fonction est déterminé par le mode console. Les données sont écrites à la position actuelle du curseur. La position du curseur est mise à jour après l’opération d’écriture. Pour plus d’informations sur les descripteurs de console, consultez CreateFile.

Lors de l’écriture sur un appareil de communication, le comportement de WriteFile est déterminé par le délai d’attente de communication actuel défini et récupéré à l’aide des fonctions SetCommTimeouts et GetCommTimeouts . Des résultats imprévisibles peuvent se produire si vous ne parvenez pas à définir les valeurs de délai d’attente. Pour plus d’informations sur les délais d’attente de communication, consultez COMMTIMEOUTS.

Bien qu’une écriture à un seul secteur soit atomique, il n’est pas garanti qu’une écriture multi-secteur soit atomique, sauf si vous utilisez une transaction (autrement dit, le handle créé est un handle traité; par exemple, un handle créé à l’aide de CreateFileTransacted). Les écritures multi-secteurs mises en cache peuvent ne pas toujours être écrites immédiatement sur le disque ; Par conséquent, spécifiez FILE_FLAG_WRITE_THROUGH dans CreateFile pour vous assurer qu’une écriture multi-secteur entière est écrite sur le disque sans retards potentiels de mise en cache.

Si vous écrivez directement dans un volume qui a un système de fichiers monté, vous devez d’abord obtenir un accès exclusif au volume. Sinon, vous risquez de provoquer une altération des données ou une instabilité du système, car les écritures de votre application peuvent entrer en conflit avec d’autres modifications provenant du système de fichiers et laisser le contenu du volume dans un état incohérent. Pour éviter ces problèmes, les modifications suivantes ont été apportées dans Windows Vista et versions ultérieures :

  • Une écriture sur un handle de volume réussit si le volume n’a pas de système de fichiers monté ou si l’une des conditions suivantes est remplie :
    • Les secteurs à écrire sont des secteurs de démarrage.
    • Secteurs à écrire pour résider en dehors de l’espace du système de fichiers.
    • Vous avez explicitement verrouillé ou démonté le volume à l’aide de FSCTL_LOCK_VOLUME ou de FSCTL_DISMOUNT_VOLUME.
    • Le volume n’a pas de système de fichiers réel. (En d’autres termes, il a un système de fichiers RAW monté.)
  • Une écriture sur un handle de disque réussit si l’une des conditions suivantes est remplie :
    • Les secteurs à écrire ne se situent pas dans les étendues d’un volume.
    • Les secteurs à écrire se trouvent dans un volume monté, mais vous avez explicitement verrouillé ou démonté le volume à l’aide de FSCTL_LOCK_VOLUME ou de FSCTL_DISMOUNT_VOLUME.
    • Les secteurs à écrire se trouvent dans un volume qui n’a pas de système de fichiers monté autre que RAW.
Il existe des exigences strictes pour utiliser correctement les fichiers ouverts avec CreateFile à l’aide de FILE_FLAG_NO_BUFFERING. Pour plus d’informations, consultez Mise en mémoire tampon des fichiers.

Si hFile a été ouvert avec FILE_FLAG_OVERLAPPED, les conditions suivantes sont appliquées :

  • Le paramètre lpOverlapped doit pointer vers une structure chevauchement unique et valide, sinon la fonction peut signaler à tort que l’opération d’écriture est terminée.
  • Le paramètre lpNumberOfBytesWritten doit avoir la valeur NULL. Pour obtenir le nombre d’octets écrits, utilisez la fonction GetOverlappedResult . Si le paramètre hFile est associé à un port d’achèvement des E/S, vous pouvez également obtenir le nombre d’octets écrits en appelant la fonction GetQueuedCompletionStatus .
Dans Windows Server 2012, cette fonction est prise en charge par les technologies suivantes.
Technologie Prise en charge
Protocole Server Message Block (SMB) 3.0 Oui
Basculement transparent SMB 3.0 (TFO) Oui
SMB 3.0 avec partages de fichiers avec montée en puissance parallèle (SO) Oui
Système de fichiers du volume partagé de cluster (CsvFS) Oui
Système de fichiers résilient (ReFS) Oui
 

Synchronisation et position du fichier

Si hFile est ouvert avec FILE_FLAG_OVERLAPPED, il s’agit d’un handle de fichier asynchrone ; sinon, il est synchrone. Les règles d’utilisation de la structure CHEVAUCHEMENT SONT légèrement différentes pour chacune d’elles, comme indiqué précédemment.
Note Si un fichier ou un appareil est ouvert pour des E/S asynchrones, les appels suivants à des fonctions telles que WriteFile à l’aide de ce handle sont généralement retournés immédiatement, mais peuvent également se comporter de manière synchrone en ce qui concerne l’exécution bloquée. Pour plus d’informations, consultez http://support.microsoft.com/kb/156932.
 
Considérations relatives à l’utilisation de handles de fichiers asynchrones :
  • WriteFile peut retourner avant la fin de l’opération d’écriture. Dans ce scénario, WriteFile retourne FALSE et la fonction GetLastError retourne ERROR_IO_PENDING, ce qui permet au processus appelant de continuer pendant que le système termine l’opération d’écriture.
  • Le paramètre lpOverlapped ne doit pas être NULL et doit être utilisé avec les faits suivants à l’esprit :
    • Bien que l’événement spécifié dans la structure OVERLAPPED soit défini et réinitialisé automatiquement par le système, le décalage spécifié dans la structure OVERLAPPED n’est pas automatiquement mis à jour.
    • WriteFile réinitialise l’événement à un état non signé lorsqu’il commence l’opération d’E/S.
    • L’événement spécifié dans la structure OVERLAPPED est défini sur un état signalé lorsque l’opération d’écriture est terminée ; jusqu’à ce moment, l’opération d’écriture est considérée comme en attente.
    • Étant donné que l’opération d’écriture commence au décalage spécifié dans la structure OVERLAPPED , et que WriteFile peut retourner avant la fin de l’opération d’écriture au niveau du système (écriture en attente), ni le décalage ni aucune autre partie de la structure ne doivent être modifiés, libérés ou réutilisés par l’application jusqu’à ce que l’événement soit signalé (autrement dit, l’écriture se termine).
Considérations relatives à l’utilisation de descripteurs de fichiers synchrones :
  • Si lpOverlapped a la valeur NULL, l’opération d’écriture commence à la position de fichier actuelle et WriteFile ne retourne pas tant que l’opération n’est pas terminée et que le système met à jour le pointeur de fichier avant que WriteFile ne retourne.
  • Si lpOverlapped n’a pas la valeur NULL, l’opération d’écriture commence au décalage spécifié dans la structure OVERLAPPED et WriteFile ne retourne pas tant que l’opération d’écriture n’est pas terminée. Le système met à jour les champs Interne et InternalHigh chevauchants et le pointeur de fichier avant que WriteFile ne retourne.
Pour plus d’informations, consultez CreateFile et E/S synchrones et asynchrones.

Tuyaux

Si un canal anonyme est utilisé et que le handle de lecture a été fermé, lorsque WriteFile tente d’écrire à l’aide du handle d’écriture correspondant du canal, la fonction retourne FALSE et GetLastError retourne ERROR_BROKEN_PIPE.

Si la mémoire tampon du canal est saturée lorsqu’une application utilise la fonction WriteFile pour écrire dans un canal, l’opération d’écriture peut ne pas se terminer immédiatement. L’opération d’écriture est terminée lorsqu’une opération de lecture (à l’aide de la fonction ReadFile ) rend plus d’espace de mémoire tampon système disponible pour le canal.

Lors de l’écriture dans un handle de canal en mode octet non bloquant avec un espace de mémoire tampon insuffisant, WriteFile retourne TRUE avec *lpNumberOfBytesWritten<nNumberOfBytesToWrite.

Pour plus d’informations sur les canaux, consultez Canaux.

Opérations traitées

S’il existe une transaction liée au descripteur de fichier, l’écriture du fichier est traitée. Pour plus d’informations, consultez À propos de NTFS transactionnel.

Exemples

Pour obtenir des exemples, consultez Création et utilisation d’un fichier temporaire et Ouverture d’un fichier pour la lecture ou l’écriture.

L’exemple C++ suivant montre comment aligner des secteurs pour les écritures de fichiers sans débogage. La variable Size est la taille du bloc de données d’origine que vous souhaitez écrire dans le fichier. Pour obtenir des règles supplémentaires concernant les E/S de fichiers non mises en mémoire tampon, consultez Mise en mémoire tampon des fichiers.
#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;
}

Spécifications

   
Client minimal pris en charge Windows XP [applications de bureau | applications UWP]
Serveur minimal pris en charge Windows Server 2003 [applications de bureau | applications UWP]
Plateforme cible Windows
En-tête fileapi.h (inclure Windows.h)
Bibliothèque Kernel32.lib
DLL Kernel32.dll

Voir aussi

CancelIo

CancelIoEx

CancelSynchronousIo

CreateFile

CreateFileTransacted

Fonctions de gestion des fichiers

Obtenir la dernière erreur

GetOverlappedResult

GetQueuedCompletionStatus

ReadFile

SetEndOfFile

WriteFileEx