Función WriteFile (fileapi.h)

Escribe datos en el archivo o en el dispositivo de entrada y salida (E/S) especificados.

Esta función está diseñada para la operación sincrónica y asincrónica. Para obtener una función similar diseñada únicamente para la operación asincrónica, consulte WriteFileEx.

Sintaxis

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

Parámetros

[in] hFile

Identificador del archivo o dispositivo de E/S (por ejemplo, un archivo, secuencia de archivos, disco físico, volumen, búfer de consola, unidad de cinta, socket, recurso de comunicaciones, mailslot o canalización).

El parámetro hFile debe haberse creado con el acceso de escritura. Para obtener más información, vea Derechos de acceso genéricos y Derechos de acceso y seguridad de archivos.

En el caso de las operaciones de escritura asincrónicas, hFile puede ser cualquier identificador abierto con la función CreateFile mediante la marca FILE_FLAG_OVERLAPPED o un identificador de socket devuelto por el socket o la función accept .

[in] lpBuffer

Puntero al búfer que contiene los datos que se van a escribir en el archivo o dispositivo.

Este búfer debe permanecer válido durante la operación de escritura. El autor de la llamada no debe usar este búfer hasta que se complete la operación de escritura.

[in] nNumberOfBytesToWrite

Número de bytes que se van a escribir en el archivo o dispositivo.

Un valor de cero especifica una operación de escritura nula. El comportamiento de una operación de escritura nula depende del sistema de archivos subyacente o la tecnología de comunicaciones.

Windows Server 2003 y Windows XP: Las operaciones de escritura de canalización a través de una red tienen un tamaño limitado por escritura. La cantidad varía por plataforma. Para plataformas x86, es de 63,97 MB. Para plataformas x64, es de 31,97 MB. Para Itanium es de 63,95 MB. Para obtener más información sobre las canalizaciones, consulte la sección Comentarios.

[out, optional] lpNumberOfBytesWritten

Puntero a la variable que recibe el número de bytes escritos al usar un parámetro hFile sincrónico. WriteFile establece este valor en cero antes de realizar cualquier comprobación de errores o trabajo. Use NULL para este parámetro si se trata de una operación asincrónica para evitar resultados potencialmente erróneos.

Este parámetro solo puede ser NULL cuando el parámetro lpOverlapped no es NULL.

Windows 7: Este parámetro no puede ser NULL.

Para obtener más información, vea la sección Comentarios.

[in, out, optional] lpOverlapped

Se requiere un puntero a una estructura SUPERPUESTA si el parámetro hFile se abrió con FILE_FLAG_OVERLAPPED; de lo contrario, este parámetro puede ser NULL.

Para un hFile que admita desplazamientos de bytes, si usa este parámetro, debe especificar un desplazamiento de bytes en el que empezar a escribir en el archivo o dispositivo. Este desplazamiento se especifica estableciendo los miembros Offset y OffsetHigh de la estructura SUPERPUESTA . En el caso de un hFile que no admite desplazamientos de bytes, se omite OffsetHigh y OffsetHigh.

Para escribir al final del archivo, especifique los miembros Offset y OffsetHigh de la estructura SUPERPUESTA como 0xFFFFFFFF. Esto es funcionalmente equivalente a llamar previamente a la función CreateFile para abrir hFile mediante FILE_APPEND_DATA acceso.

Para obtener más información sobre las diferentes combinaciones de lpOverlapped y FILE_FLAG_OVERLAPPED, vea la sección Comentarios y la sección Sincronización y posición de archivo .

Valor devuelto

Si la función se ejecuta correctamente, el valor devuelto es distinto de cero (TRUE).

Si se produce un error en la función o se completa de forma asincrónica, el valor devuelto es cero (FALSE). Para obtener información ampliada de los errores, llame a la función GetLastError.

Nota El código GetLastErrorERROR_IO_PENDING no es un error; designa que la operación de escritura está pendiente de finalización de forma asincrónica. Para obtener más información, vea la sección Comentarios.
 

Comentarios

La función WriteFile devuelve cuando se produce una de las condiciones siguientes:

  • Se escribe el número de bytes solicitados.
  • Una operación de lectura libera el espacio del búfer en el extremo de lectura de la canalización (si se bloqueó la escritura). Para obtener más información, consulte la sección Canalizaciones .
  • Se usa un identificador asincrónico y la escritura se está produciendo de forma asincrónica.
  • Se produce un error.
Es posible que se produzca un error en la función WriteFilecon ERROR_INVALID_USER_BUFFER o ERROR_NOT_ENOUGH_MEMORY siempre que haya demasiadas solicitudes de E/S asincrónicas pendientes.

Para cancelar todas las operaciones de E/S asincrónicas pendientes, use:

  • CancelIo: esta función cancela solo las operaciones emitidas por el subproceso que realiza la llamada para el identificador de archivo especificado.
  • CancelIoEx: esta función cancela todas las operaciones emitidas por los subprocesos para el identificador de archivo especificado.
Use la función CancelSynchronousIo para cancelar las operaciones de E/S sincrónicas pendientes.

Las operaciones de E/S que se cancelan se completan con el error ERROR_OPERATION_ABORTED.

Es posible que se produzca un error en la función WriteFilecon ERROR_NOT_ENOUGH_QUOTA, lo que significa que el búfer del proceso de llamada no pudo estar bloqueado por páginas. Para obtener más información, vea SetProcessWorkingSetSize.

Si otro proceso bloquea parte del archivo y la operación de escritura se superpone a la parte bloqueada, WriteFile produce un error.

Al escribir en un archivo, la hora de la última escritura no se actualiza completamente hasta que se hayan cerrado todos los identificadores usados para escribir. Por lo tanto, para garantizar una hora de última escritura precisa, cierre el identificador de archivo inmediatamente después de escribir en el archivo.

El acceso al búfer de salida mientras una operación de escritura usa el búfer puede provocar daños en los datos escritos desde ese búfer. Las aplicaciones no deben escribir en, reasignar ni liberar el búfer de salida que usa una operación de escritura hasta que se complete la operación de escritura. Esto puede ser especialmente problemático cuando se usa un identificador de archivo asincrónico. Puede encontrar información adicional sobre los identificadores de archivos sincrónicos frente a asincrónicos más adelante en la sección Sincronización y posición de archivo y E /S sincrónica y asincrónica.

Tenga en cuenta que es posible que las marcas de tiempo no se actualicen correctamente para un archivo remoto. Para garantizar resultados coherentes, use E/S sin búfer.

El sistema interpreta cero bytes para escribir como especificar una operación de escritura nula y WriteFile no trunca ni extiende el archivo. Para truncar o extender un archivo, use la función SetEndOfFile .

Los caracteres se pueden escribir en el búfer de pantalla mediante WriteFile con un identificador para la salida de la consola. El comportamiento exacto de la función viene determinado por el modo de consola. Los datos se escriben en la posición actual del cursor. La posición del cursor se actualiza después de la operación de escritura. Para obtener más información sobre los identificadores de consola, vea CreateFile.

Al escribir en un dispositivo de comunicaciones, el comportamiento de WriteFile viene determinado por el tiempo de espera de comunicación actual establecido y recuperado mediante las funciones SetCommTimeouts y GetCommTimeouts . Se pueden producir resultados imprevisibles si no se pueden establecer los valores de tiempo de espera. Para obtener más información sobre los tiempos de espera de comunicación, consulte COMMTIMEOUTS.

Aunque una escritura de un solo sector es atómica, no se garantiza que una escritura de varios sectores sea atómica a menos que use una transacción (es decir, el identificador creado es un identificador de transacción; por ejemplo, un identificador creado mediante CreateFileTransacted). Es posible que las escrituras de varios sectores que se almacenan en caché no siempre se escriban en el disco de inmediato; por lo tanto, especifique FILE_FLAG_WRITE_THROUGH en CreateFile para asegurarse de que se escribe una escritura en todo el sector en el disco sin retrasos potenciales en el almacenamiento en caché.

Si escribe directamente en un volumen que tiene un sistema de archivos montado, primero debe obtener acceso exclusivo al volumen. De lo contrario, corre el riesgo de causar daños en los datos o inestabilidad del sistema, ya que las escrituras de la aplicación pueden entrar en conflicto con otros cambios procedentes del sistema de archivos y dejar el contenido del volumen en un estado incoherente. Para evitar estos problemas, se han realizado los siguientes cambios en Windows Vista y versiones posteriores:

  • Una escritura en un identificador de volumen se realizará correctamente si el volumen no tiene un sistema de archivos montado o si se cumple una de las condiciones siguientes:
    • Los sectores en los que se va a escribir son sectores de arranque.
    • Sectores que se van a escribir para residir fuera del espacio del sistema de archivos.
    • Ha bloqueado o desmontado explícitamente el volumen mediante FSCTL_LOCK_VOLUME o FSCTL_DISMOUNT_VOLUME.
    • El volumen no tiene ningún sistema de archivos real. (En otras palabras, tiene montado un sistema de archivos RAW).
  • Una escritura en un identificador de disco se realizará correctamente si se cumple una de las condiciones siguientes:
    • Los sectores que se van a escribir no se encuentran dentro de las extensiones de un volumen.
    • Los sectores que se van a escribir se encuentran dentro de un volumen montado, pero se ha bloqueado o desmontado explícitamente el volumen mediante FSCTL_LOCK_VOLUME o FSCTL_DISMOUNT_VOLUME.
    • Sectores que se van a escribir para que se incluyan en un volumen que no tenga ningún sistema de archivos montado que no sea RAW.
Hay requisitos estrictos para trabajar correctamente con archivos abiertos con CreateFile mediante FILE_FLAG_NO_BUFFERING. Para obtener más información, consulte Almacenamiento en búfer de archivos.

Si hFile se abrió con FILE_FLAG_OVERLAPPED, se aplican las condiciones siguientes:

  • El parámetro lpOverlapped debe apuntar a una estructura SUPERPUESTA válida y única; de lo contrario, la función puede informar incorrectamente de que la operación de escritura está completa.
  • El parámetro lpNumberOfBytesWritten debe establecerse en NULL. Para obtener el número de bytes escritos, use la función GetOverlappedResult . Si el parámetro hFile está asociado a un puerto de finalización de E/S, también puede obtener el número de bytes escritos llamando a la función GetQueuedCompletionStatus .
En Windows Server 2012, esta función es compatible con las siguientes tecnologías.
Tecnología Compatible
Protocolo Bloque de mensajes del servidor (SMB) 3.0
Conmutación por error transparente (TFO) de SMB 3.0
SMB 3.0 con recursos compartidos de archivos de escalabilidad horizontal (SO)
Sistema de archivos de Volumen compartido de clúster (CsvFS)
Sistema de archivos resistente a errores (ReFS)
 

Sincronización y posición de archivo

Si hFile se abre con FILE_FLAG_OVERLAPPED, es un identificador de archivo asincrónico; de lo contrario, es sincrónica. Las reglas para usar la estructura SUPERPUESTA son ligeramente diferentes para cada una, como se indicó anteriormente.
Nota Si se abre un archivo o dispositivo para E/S asincrónica, las llamadas posteriores a funciones como WriteFile mediante ese identificador suelen devolverse inmediatamente, pero también pueden comportarse de forma sincrónica con respecto a la ejecución bloqueada. Para más información, consulte http://support.microsoft.com/kb/156932.
 
Consideraciones para trabajar con identificadores de archivos asincrónicos:
  • WriteFile puede devolver antes de que se complete la operación de escritura. En este escenario, WriteFile devuelve FALSE y la función GetLastError devuelve ERROR_IO_PENDING, lo que permite que el proceso de llamada continúe mientras el sistema completa la operación de escritura.
  • El parámetro lpOverlapped no debe ser NULL y debe usarse teniendo en cuenta los siguientes hechos:
    • Aunque el sistema establece y restablece automáticamente el evento especificado en la estructura SUPERPUESTA , el desplazamiento especificado en la estructura SUPERPUESTA no se actualiza automáticamente.
    • WriteFile restablece el evento en un estado no asignado cuando comienza la operación de E/S.
    • El evento especificado en la estructura SUPERPUESTA se establece en un estado señalado cuando se completa la operación de escritura; hasta ese momento, la operación de escritura se considera pendiente.
    • Dado que la operación de escritura se inicia en el desplazamiento especificado en la estructura SUPERPUESTA , y WriteFile puede devolver antes de que se complete la operación de escritura en el nivel del sistema (escritura pendiente), ni el desplazamiento ni ninguna otra parte de la estructura deben modificarse, liberarse o reutilizarse por la aplicación hasta que se señale el evento (es decir, la escritura se completa).
Consideraciones para trabajar con identificadores de archivo sincrónicos:
  • Si lpOverlapped es NULL, la operación de escritura se inicia en la posición del archivo actual y WriteFile no devuelve hasta que se complete la operación y el sistema actualiza el puntero de archivo antes de que WriteFile devuelva.
  • Si lpOverlapped no es NULL, la operación de escritura se inicia en el desplazamiento especificado en la estructura SUPERPUESTA y WriteFile no devuelve hasta que se complete la operación de escritura. El sistema actualiza los campos INTERNAL y InternalHigh superpuestos y el puntero de archivo antes de que Se devuelva WriteFile .
Para obtener más información, vea CreateFile y Sincrónico y E/S asincrónico.

Tuberías

Si se usa una canalización anónima y se cierra el identificador de lectura, cuando WriteFile intenta escribir con el identificador de escritura correspondiente de la canalización, la función devuelve FALSE y GetLastError devuelve ERROR_BROKEN_PIPE.

Si el búfer de canalización está lleno cuando una aplicación usa la función WriteFile para escribir en una canalización, es posible que la operación de escritura no finalice inmediatamente. La operación de escritura se completará cuando una operación de lectura (mediante la función ReadFile ) haga que haya más espacio en el búfer del sistema disponible para la canalización.

Al escribir en un controlador de canalización sin bloqueo, el modo de bytes con espacio de búfer insuficiente, WriteFile devuelve TRUE con *lpNumberOfBytesWritten<nNumberOfBytesToWrite.

Para obtener más información sobre las canalizaciones, consulte Canalizaciones.

Operaciones de transacción

Si hay una transacción enlazada al identificador de archivo, se realiza una transacción de escritura de archivo. Para obtener más información, vea Acerca de NTFS transaccional.

Ejemplos

Para obtener algunos ejemplos, vea Crear y usar un archivo temporal y abrir un archivo para leer o escribir.

En el ejemplo de C++ siguiente se muestra cómo alinear sectores para las escrituras de archivos no almacenados en búfer. La variable Size es el tamaño del bloque de datos original que le interesa escribir en el archivo. Para obtener reglas adicionales relacionadas con la E/S de archivos no almacenados en búfer, consulte Almacenamiento en búfer de archivos.
#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;
}

Requisitos

   
Cliente mínimo compatible Windows XP [aplicaciones de escritorio | aplicaciones para UWP]
Servidor mínimo compatible Windows Server 2003 [aplicaciones de escritorio | aplicaciones para UWP]
Plataforma de destino Windows
Encabezado fileapi.h (incluya Windows.h)
Library Kernel32.lib
Archivo DLL Kernel32.dll

Vea también

CancelIo

CancelIoEx

CancelSynchronousIo

CreateFile

CreateFileTransacted

Funciones de administración de archivos

Obtener último error

GetOverlappedResult

GetQueuedCompletionStatus

ReadFile

SetEndOfFile

WriteFileEx