有没有类似于fdopen用于HANDLE的Windows等价物?

35

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

在Windows上是否有与HANDLE相对应的类似方法呢?如果您有一个从父进程继承而来的HANDLE(不同于stdin、stdout或stderr)或从CreatePipe返回的管道,是否可能从中获取一个带缓冲的FILE*流呢?MSDN确实记录了_fdopen,但该函数仅适用于由_open返回的整数文件描述符,而不是通用的HANDLE

2个回答

46
很不幸,HANDLEFILE*和文件描述符是完全不同的实体。CRT最终通过HANDLE处理文件,并将这些HANDLE关联到文件描述符上。转而回来,这些文件描述符会支持指向FILE*的结构指针。
幸运的是,此MSDN页面上有一个部分介绍了“提供在FILE结构,文件描述符和Win32文件句柄之间更改文件表示的方法”的函数:
  • _fdopen_wfdopen:将流与以前为低级I/O打开的文件关联并返回指向打开流的指针。
  • _fileno:获取与流关联的文件描述符。
  • _get_osfhandle:返回与现有C运行时文件描述符关联的操作系统文件句柄
  • _open_osfhandle:将C运行时文件描述符与现有操作系统文件句柄关联。
看起来你需要的是_open_osfhandle ,然后使用_fdopen来从HANDLE获取FILE*
下面是一个涉及使用CreateFile()获取HANDLE的示例。当我测试它时,它会显示文件“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);
        }
    }
}

这也适用于管道。


0

这里有一种更优雅的方法来代替CreateFile:在fopen()中指定“N”。这是一个Microsoft特定的扩展,但由于此代码已经是平台特定的,所以没问题。当使用“N”调用时,fopen在内部调用_open时添加_O_NOINHERIT标志。

基于此: Windows C运行时_close(fd)未关闭文件


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接