Wenn Sie unter Unix einen Dateideskriptor haben (z. B. von einem Socket, einer Pipe oder von Ihrem übergeordneten Prozess geerbt), können Sie eine gepufferte E/A öffnen FILE*
streamen Sie darauf mit fdopen(3)
.
Gibt es ein Äquivalent unter Windows für HANDLE
s? Wenn Sie eine haben HANDLE
das von Ihrem übergeordneten Prozess (anders als stdin, stdout oder stderr) oder einer Pipe von geerbt wurde CreatePipe
ist es möglich, eine gepufferte zu bekommen FILE*
daraus streamen? MSDN dokumentiert _fdopen
aber das funktioniert mit ganzzahligen Dateideskriptoren, die von zurückgegeben werden _open
nicht generisch HANDLE
s.
Leider, HANDLE
s sind ganz andere Bestien aus FILE*
s und Dateideskriptoren. Die CRT verarbeitet Dateien letztendlich in Bezug auf HANDLE
s und assoziiert diese HANDLE
s zu einem Dateideskriptor. Diese Dateideskriptoren wiederum unterstützen den Strukturzeiger um FILE*
.
Glücklicherweise gibt es einen Abschnitt auf diese MSDN-Seite das beschreibt Funktionen, die “eine Möglichkeit bieten, die Darstellung der Datei zwischen a DATEI Struktur, ein Dateideskriptor und ein Win32-Dateihandle”:
_fdopen
, _wfdopen
: Ordnet einen Stream einer Datei zu, die zuvor für Low-Level-E/A geöffnet wurde, und gibt einen Zeiger auf den geöffneten Stream zurück.
_fileno
: Ruft den Dateideskriptor ab, der einem Stream zugeordnet ist.
_get_osfhandle
: Geben Sie das Dateihandle des Betriebssystems zurück, das dem vorhandenen C-Laufzeitdateideskriptor zugeordnet ist
_open_osfhandle
: Verknüpft den C-Laufzeit-Dateideskriptor mit einem vorhandenen Datei-Handle des Betriebssystems.
Sieht aus wie das, was Sie brauchen _open_osfhandle
gefolgt von _fdopen
ein erhalten FILE*
von einem HANDLE
.
Hier ist ein Beispiel mit HANDLE
s erhalten von CreateFile()
. Als ich es getestet habe, zeigt es die ersten 255 Zeichen der Datei “test.txt” und hängt ” — Hello World! — ” am Ende der Datei an:
#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);
}
}
}
Dies sollte auch für Rohre funktionieren.
Hier ist ein eleganterer Weg, dies anstelle von CreateFile zu tun: Geben Sie “N” in fopen() an. Es ist eine Microsoft-spezifische Erweiterung von fopen, aber da dieser Code sowieso plattformspezifisch ist, ist es in Ordnung. Wenn es mit “N” aufgerufen wird, fügt fopen das _O_NOINHERIT-Flag hinzu, wenn _open intern aufgerufen wird.
Basierend darauf: Windows C Run-Time _close(fd) schließt Datei nicht