【问题标题】:Is there a Windows equivalent to fdopen for HANDLEs?对于 HANDLE,是否有与 fdopen 等效的 Windows?
【发布时间】:2011-11-14 05:29:37
【问题描述】:

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

在 Windows 上是否有 HANDLEs 的等价物?如果您有一个从父进程(不同于 stdin、stdout 或 stderr)继承的 HANDLE 或来自 CreatePipe 的管道,是否可以从中获取缓冲的 FILE* 流? MSDN 确实记录了_fdopen,但它适用于_open 返回的整数文件描述符,而不是通用的HANDLEs。

【问题讨论】:

    标签: c winapi stdio


    【解决方案1】:

    不幸的是,HANDLEs 与 FILE*s 和文件描述符完全不同。 CRT 最终根据HANDLEs 处理文件,并将这些HANDLEs 与文件描述符相关联。这些文件描述符反过来通过FILE*支持结构指针。

    幸运的是,this MSDN page 上有一个部分描述了“提供一种在 FILE 结构、文件描述符和 Win32 文件句柄之间更改文件表示的方法” :

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

    看起来您需要_open_osfhandle 后跟_fdopen 以从HANDLE 获取FILE*

    这是一个涉及从CreateFile() 获得的HANDLEs 的示例。当我测试它时,它显示了文件“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);
            }
        }
    }
    

    这也适用于管道。

    【讨论】:

      【解决方案2】:

      这里有一个比 CreateFile 更优雅的方法:在 fopen() 中指定“N”。这是 fopen 的 Microsoft 特定扩展,但由于此代码无论如何都是特定于平台的,所以没关系。使用“N”调用时,fopen 在内部调用 _open 时会添加 _O_NOINHERIT 标志。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-01
        • 2012-09-05
        • 2019-12-11
        • 1970-01-01
        相关资源
        最近更新 更多