Есть ли в Windows эквивалент fdopen для РУЧКИ? - PullRequest
30 голосов
/ 10 сентября 2011

В Unix, если у вас есть файловый дескриптор (например, из сокета, канала или унаследованный от вашего родительского процесса), вы можете открыть буферизованный поток ввода-вывода FILE* для него с помощью fdopen(3).

Есть ли в Windows эквивалент для HANDLE s?Если у вас есть HANDLE, который был унаследован от вашего родительского процесса (отличается от stdin, stdout или stderr) или канала от CreatePipe, возможно ли получить буферизованный поток FILE* из него?MSDN документирует _fdopen, но это работает с целочисленными файловыми дескрипторами, возвращаемыми _open, а не с общими HANDLE s.

1 Ответ

40 голосов
/ 10 сентября 2011

К сожалению, HANDLE s - это совершенно разные звери от FILE* s и файловые дескрипторы.В конечном итоге CRT обрабатывает файлы с точки зрения HANDLE s и связывает эти HANDLE s с дескриптором файла.Эти файловые дескрипторы, в свою очередь, поддерживают указатель структуры на FILE*.

. К счастью, на этой странице MSDN есть раздел , в котором описываются функции, которые «предоставляют способ изменить представлениефайл между структурой FILE , дескриптором файла и дескриптором файла Win32 ":

  • _fdopen, _wfdopen: связывает поток с файлом, которыйранее был открыт для низкоуровневого ввода-вывода и возвращает указатель на открытый поток.
  • _fileno: получает дескриптор файла, связанный с потоком.
  • _get_osfhandle: возвращать работу-системный дескриптор файла, связанный с существующим дескриптором файла времени выполнения C
  • _open_osfhandle: Связывает дескриптор файла времени выполнения C с существующим дескриптором файла операционной системы.

Похоже, вам нужно _open_osfhandle, за которым следует _fdopen, чтобы получить FILE* из HANDLE.

Вот пример, включающий HANDLE s получено из CreateFile().Когда я тестировал его, он показывает первые 255 символов файла «test.txt» и добавляет «--- 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);
        }
    }
}

Это должноработать и для труб.

...