是否有一个Windows等同于HANDLEs的fdopen?

时间:2011-09-10 03:36:36

标签: c winapi stdio

在Unix中,如果您有文件描述符(例如来自套接字,管道或从父进程继承),则可以使用fdopen(3)在其上打开缓冲的I / O FILE*流。

Windows HANDLE上是否有相应的内容?如果您的父进程(与stdin,stdout或stderr不同)或来自HANDLE的管道继承了CreatePipe,是否可以从中获取缓冲的FILE*流它? MSDN会记录_fdopen,但它适用于_open返回的整数文件描述符,而非通用HANDLE

2 个答案:

答案 0 :(得分:40)

不幸的是,HANDLEFILE*和文件描述符完全不同。 CRT最终根据HANDLE处理文件,并将这些HANDLE与文件描述符相关联。这些文件描述符依次将结构指针支持FILE*

幸运的是,this MSDN page上有一节描述了“提供一种方法来改变 FILE 结构,文件描述符和Win32文件之间文件表示的方法”处理“:

  
      
  • _fdopen_wfdopen:将流与文件关联   之前为低级I / O打开并返回指向open的指针   流。
  •   
  • _fileno:获取与流关联的文件描述符。
  •   
  • _get_osfhandle:返回关联的操作系统文件句柄   使用现有的C运行时文件描述符
  •   
  • _open_osfhandle:将C运行时文件描述符与a关联   现有的操作系​​统文件句柄。
  •   

您需要的是_open_osfhandle,然后是_fdopen,以便从FILE*获取HANDLE

以下是从HANDLE获取CreateFile()的示例。当我测试它时,它会显示文件“test.txt”的前255个字符,并在文件末尾附加“--- 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);
        }
    }
}

这也适用于管道。

答案 1 :(得分:0)

这是一种比CreateFile更优雅的方法:在fopen()中指定“ N”。它是fopen的Microsoft特定扩展,但由于此代码还是特定于平台的,因此可以。当用“ N”调用时,fopen在内部调用_open时会添加_O_NOINHERIT标志。

基于此: Windows C Run-Time _close(fd) not closing file