winbase.h


ReadFile

Lee datos desde un fichero, comenzando en la posición indicada por el puntero del fichero. Después de que la operación de lectura ha sido completada, el puntero del fichero se ajusta según el número de bytes leídos, a no ser que el manipulador de fichero haya sido creado con el atributo de superposición (overlapped). Si el manipulador de fichero es creado para entradas y salidas superpuestas (overlapped I/O), la aplicación debe ajustar la posición del puntero del fichero después de la operación de lectura.

Sintaxis

BOOL ReadFile(
    HANDLE hFile,                 // manipulador del fichero
    LPVOID lpBuffer,              // dirección del buffer que recibirá los datos
    DWORD nNumberOfBytesToRead,   // número de bytes a leer
    LPDWORD lpNumberOfBytesRead,  // dirección del número de bytes leídos 
    LPOVERLAPPED lpOverlapped     // dirección de la estructura para datos
   );

Parámetros:

hFile: identifica el fichero del que se leerá. El manipulador debe haber sido creado con acceso GENERIC_READ al fichero.

Windows NT: para operaciones de lectura asíncronas, hFile puede ser un manipulador abierto con el flag FILE_FLAG_OVERLAPPED en la función CreateFile, o un manipulador de socket devuelto por las funciones socket o accept.

Windows 95: para operaciones de lectura asíncronas, hFile puede ser un manipulador de un recurso de comunicaciones, un mailslot o de una tubería con nombre (named pipe) abierto con el flag FILE_FLAG_OVERLAPPED por la función CreateFile, o un manipulador de socket devuelto por las funciones socket o accept. Windows 95 no soporta operaciones de lectura asíncronas en ficheros de disco.

lpBuffer: puntero al buffer que recibirá los datos leídos desde el fichero.

nNumberOfBytesToRead: especifica el número de bytes a leer desde el fichero.

lpNumberOfBytesRead: apunta al número de bytes leídos. ReadFile cambia este valor a cero antes de hacer ningún trabajo o comprobación de error. Si este parámetro es cero cuando ReadFile regresa con TRUE en una tubería con nombre, es porque el otro extremo de la tubería en modo mensaje llamó a la función WriteFile con el parámetro nNumberOfBytesToWrite a cero.

lpOverlapped: apunta a una estructura OVERLAPPED. Esta estructura se requiere si hFile fue creado con FILE_FLAG_OVERLAPPED.

Este parámetro no puede ser NULL si hFile fue abierto con FILE_FLAG_OVERLAPPED. Debe apuntar a una estructura OVERLAPPED válida. Si hFile fue creado con FILE_FLAG_OVERLAPPED y lpOverlapped es NULL, la función falla de modo impredecible.

Si hFile fue creado con FILE_FLAG_OVERLAPPED y lpOverlapped es NULL, la operación de lectura empieza en la posición del fichero actual y ReadFile puede regresar antes de que la operación haya sido completada. En este caso ReadFile revuelve FALSE y la función GetLastError devuelve ERROR_IO_PENDING. El proceso que llama puede continuar mientras la operación de lectura termina. El evento especificado el la estructura OVERLAPPED se modifica al estado de señalizado hasta que se completa la operación de lectura.

Si hFile no fue creado con FILE_FLAG_OVERLAPPED y lpOverlapped no es NULL, la operación de lectura comienza con el desplazamiento especificado en la estructura OVERLAPPED. ReadFile no regresa mientras la operación de lectura no se haya completado.

Si hFile o fue creado con FILE_FLAG_OVERLAPPED y lpOverlapped no es NULL, la operación de escritura comienza a partir del desplazamiento indicado en la estructura OVERLAPPED y WriteFile no regresa hasta que se completa la operación de escritura.

Valor de retorno

Si la función tiene éxito, el valor de retorno es TRUE. Si el valor de retorno es TRUE y el número de bytes leídos es cero, el puntero del fichero estaba más allá del final de fichero actual en el momento de la operación de lectura.

Si la función falla, el valor de retorno es FALSE. Para obtener mayor información sobre el error, llamar a GetLastError.

Observaciones

Si parte del fichero está bloqueado por otro proceso y la operación de lectura sobrepasa la porción bloqueada, esta función falla.

Las aplicaciones no deben leer ni escribir en el buffer de entrada que una operación de lectura esté usando mientras la operación de lectura no se complete. Un acceso prematuro al buffer de entrada puede provocar una corrupción de los datos leídos en ese buffer.

Los caracteres pueden ser leídos desde el buffer de consola usando ReadFile con un manipulador de consola de entrada. El comportamiento exacto de la función se determina según el modo de consola.

Si una tubería con nombre (named pipe) está siendo leída en modo mensaje el siguiente mensaje es más largo que el parámetro nNumberOfBytesToRead especificado, ReadFile devuelve FALSE y GetLastError devuelve ERROR_MORE_DATA. El resto del mensaje puede ser leído sólo por una nueva llamada a ReadFile o a PeekNamedPipe.

Cuando se lee desde un dispositivo de comunicaciones, el comportamiento de ReadFile depende de los límites de tiempo de comunicación que se modifican o recuperan usando las funciones SetCommTimeouts y GetCommTimeouts. Pueden obtenerse resultados impredecibles si se falla al cambiar los valores de los tiempos de respuesta. Para más información sobre límites de tiempos de comunicaciones, ver COMMTIMEOUTS.

Si ReadFile intenta leer desde un mailslot cuyo buffer es demasiado pequeño, la función devuelve FALSE y GetLastError devuelve ERROR_INSUFFICIENT_BUFFER.

Si el manipulador de tubería anónima de escritura ha sido cerrado y ReadFile intenta leer usando el manipulador de lectura de la tubería anónima correspondiente, la función devuelve FALSE y GetLastError devuelve ERROR_BROKEN_PIPE.

La función ReadFile puede fallar con ERROR_INVALID_USER_BUFFER o ERROR_NOT_ENOUGH_MEMORY si existen demasiadas peticiones de I/O asíncronas pendientes.

Si hFile es un manipulador de una tubería con nombre, los miembros Offset y OffsetHigh de la estructura OVERLAPPED apuntada por lpOverlapped deben ser cero, o la función fallará.

El código de ReadFile para comprobar la condición de fin-de-fichero (eof) es diferente para operaciones de lectura síncronas y asíncronas.

Cuando una operación de lectura síncrona lee el fin-de-fichero, ReadFile devuelve TRUE y pone *lpNumberOfBytesRead a cero. El siguiente código de ejemplo comprueba el fin-de-fichero para una operación de lectura síncrona:

// intento de operación de lectura síncrona
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL) ; 
// comprobar eof 
if (bResult && nBytesRead == 0, ) { 
   // estamos en el final del fichero
   }

Una operación de lectura asíncrona puede encontrar el final de un fichero durante la llamada inicial a ReadFile, o durante operaciones asíncronas posteriores.

Si se detecta EOF dentro del tiempo de ReadFile para una operación de lectura asíncrona, ReadFile devuelve FALSE y GetLastError devuelve ERROR_HANDLE_EOF.

Si se detecta EOF durante subsiguientes operaciones asíncronas, la llamada a la función GetOverlappedResult para obtener el resultado de esa operación devuelve FALSE y GetLastError devuelve ERROR_HANDLE_EOF.

El siguiente código de ejemplo ilustra la comprobación del fin-de-fichero para una operación de lectura asíncrona:

// preparar los campos de la estructura overlapped
// para simplificar el ejemplo, se omite el manipulador de evento
gOverLapped.Offset     = 0; 
gOverLapped.OffsetHigh = 0; 
gOverLapped.hEvent     = NULL; 
 
// intento de operación de lectura asíncrona
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, 
		 &gOverlapped) ; 
 
// Si hubo un problema, o la operación permanece pendiente...
if (!bResult) { 
   // tratamiento del código de error
   switch (dwError = GetLastError()) { 
      case ERROR_HANDLE_EOF: { 
         // hemos leído el fin del fichero
         // durante la llamada a ReadFile 
         // código para manipular esto
      } 
      case ERROR_IO_PENDING: { 
         // se está realizando una i/o asíncrona
         // hacer otra cosa mientras
         HacerOtraCosa(); 
         // comprobar el resultado de la lectura asíncrona
         bResult = GetOverlappedResult(hFile, &gOverlapped, 
                      &nBytesRead, FALSE) ; 
         // si hubo un problema... 
         if (!bResult) { 
            // tratamiento del código de error
            switch (dwError = GetLastError()) { 
               case ERROR_HANDLE_EOF: { 
                  // hemos leído e final del fichero
                  // durante la operación asíncrona
               } 
               // tratamiento de otros casos de error
            } // fin de switch 
         } // fin de if 
      } // fin de case 
      // tratamiento de otros casos de error
   } // end switch 
} // end if