2011-09-10 20 views
27

En Unix, si tiene un descriptor de archivo (por ejemplo, de un socket, un conducto o heredado de su proceso principal), puede abrir una secuencia de E/S en búfer FILE* con fdopen(3).¿Hay un equivalente de Windows para fdopen para HANDLEs?

¿Hay un equivalente en Windows para HANDLE s? Si tiene un HANDLE que se heredó de su proceso principal (diferente de stdin, stdout o stderr) o un conducto del CreatePipe, ¿es posible obtener un flujo de FILE* en él? MSDN documenta _fdopen, pero eso funciona con los descriptores de archivos enteros devueltos por _open, no genéricos HANDLE s.

Respuesta

31

Desafortunadamente, HANDLE s son bestias completamente diferentes de FILE* sy descriptores de archivos. El CRT finalmente maneja los archivos en términos de HANDLE sy asocia esos HANDLE a un descriptor de archivo. Esos descriptores de archivo a su vez retrocede el puntero de la estructura por FILE*.

Afortunadamente, hay una sección sobre this MSDN page que describe las funciones que "proporcionan una manera de cambiar la representación del archivo entre un estructura archivo, un descriptor de archivo y un identificador de archivo Win32":

  • _fdopen, _wfdopen: asocia un flujo con un archivo que se ha abierto previamente para de bajo nivel de e/S y devuelve un puntero a la flujo abierto.
  • _fileno: Obtiene el descriptor de archivo asociado a una secuencia.
  • _get_osfhandle: mango de retorno de archivos de sistema operativo asociado con C en tiempo de ejecución descriptor de archivo
  • _open_osfhandle existente: Associates tiempo de ejecución C descriptor de archivo con un identificador de archivo del sistema operativo existente .

Parece que lo que necesita es _open_osfhandle seguido por _fdopen para obtener un FILE* de un HANDLE.

Aquí hay un ejemplo de HANDLE obtenido de CreateFile(). Cuando lo probé, que muestra los primeros 255 caracteres del "test.txt" archivo y añade al final del archivo "--- --- Hello World!":

#include <windows.h> 
#include <io.h> 
#include <fcntl.h> 
#include <cstdio> 

int main() 
{ 
    HANDLE h = CreateFile("test.txt", GENERIC_READ | GENERIC_WRITE, 0, 0, 
     OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 
    if(h != INVALID_HANDLE_VALUE) 
    { 
     int fd = _open_osfhandle((intptr_t)h, _O_APPEND | _O_RDONLY); 
     if(fd != -1) 
     { 
      FILE* f = _fdopen(fd, "a+"); 
      if(f != 0) 
      { 
       char rbuffer[256]; 
       memset(rbuffer, 0, 256); 
       fread(rbuffer, 1, 255, f); 
       printf("read: %s\n", rbuffer); 
       fseek(f, 0, SEEK_CUR); // Switch from read to write 
       const char* wbuffer = " --- Hello World! --- \n"; 
       fwrite(wbuffer, 1, strlen(wbuffer), f); 
       fclose(f); // Also calls _close() 
      } 
      else 
      { 
       _close(fd); // Also calls CloseHandle() 
      } 
     } 
     else 
     { 
      CloseHandle(h); 
     } 
    } 
} 

Esto debería funcionar para pipas también.

Cuestiones relacionadas