Ich suche im Grunde nach einer C ++ - Version von fdopen (). Ich habe ein bisschen darüber recherchiert und es ist eines dieser Dinge, die einfach zu sein scheinen, sich aber als sehr kompliziert herausstellen. Vermisse ich etwas in diesem Glauben (dh es ist wirklich einfach)? Wenn nicht, gibt es irgendwo eine gute Bibliothek, um das zu erledigen?
BEARBEITEN: Meine Beispiellösung wurde in eine separate Antwort verschoben.
c++
posix
fstream
file-descriptor
BD in Rivenhill
quelle
quelle
mmap
mit der Datei umgehen und ihren Inhalt als Byte-Array verfügbar machen.Antworten:
Aus der Antwort von Éric Malenfant:
Basierend auf den obigen Beobachtungen und meinen Recherchen unten gibt es Arbeitscode in zwei Varianten; eine für libstdc ++ und eine für Microsoft Visual C ++.
libstdc ++
Es gibt eine nicht standardmäßige
__gnu_cxx::stdio_filebuf
Klassenvorlage, diestd::basic_streambuf
den folgenden Konstruktor erbt und hatmit Beschreibung Dieser Konstruktor ordnet einen Dateistream-Puffer einem geöffneten POSIX-Dateideskriptor zu.
Wir erstellen es über das POSIX-Handle (Zeile 1) und übergeben es dann als basic_streambuf (Zeile 2) an den Konstruktor von istream:
Microsoft Visual C ++
Früher gab es eine nicht standardmäßige Version des Konstruktors von ifstream, die den POSIX-Dateideskriptor verwendet, aber er fehlt sowohl in aktuellen Dokumenten als auch im Code. Es gibt eine andere nicht standardmäßige Version des Konstruktors von ifstream, die FILE * verwendet
und es ist nicht dokumentiert (ich konnte nicht einmal eine alte Dokumentation finden, in der es vorhanden wäre). Wir nennen es (Zeile 1), wobei der Parameter das Ergebnis des Aufrufs von _fdopen ist , um den C-Stream FILE * vom POSIX- Dateihandle abzurufen .
quelle
std::cout
Implementierung ist eine gute Idee. Ich frage mich, was ist der Unterschied zwischenstdio_filebuf
undstdio_sync_filebuf
?AFAIK, dies ist in Standard-C ++ nicht möglich. Abhängig von Ihrer Plattform bietet Ihre Implementierung der Standardbibliothek möglicherweise (als nicht standardmäßige Erweiterung) einen fstream-Konstruktor, der einen Dateideskriptor (dies ist bei libstdc ++, IIRC der Fall) oder
FILE*
eine Eingabe verwendet.Eine andere Alternative wäre die Verwendung eines Boost :: iostreams :: file_descriptor- Geräts, das Sie in einen boost :: iostreams :: stream einbinden könnten, wenn Sie eine std :: stream-Schnittstelle dazu haben möchten.
quelle
Es besteht eine gute Chance, dass Ihr Compiler einen FILE-basierten fstream-Konstruktor anbietet, obwohl dieser nicht dem Standard entspricht. Beispielsweise:
Aber soweit ich weiß, gibt es keine tragbare Möglichkeit, dies zu tun.
quelle
Ein Teil der ursprünglichen (nicht angegebenen) Motivation dieser Frage besteht darin, Daten entweder zwischen Programmen oder zwischen zwei Teilen eines Testprogramms mithilfe einer sicher erstellten temporären Datei übertragen zu können, aber tmpnam () gibt eine Warnung in gcc aus, also wollte ich stattdessen mkstemp () verwenden. Hier ist ein Testprogramm, das ich basierend auf der Antwort von Éric Malenfant geschrieben habe, aber mkstemp () anstelle von fdopen () verwendet habe. Dies funktioniert auf meinem Ubuntu-System mit installierten Boost-Bibliotheken:
quelle
Es ist eigentlich ganz einfach. Nicolai M. Josuttis hat
fdstream
in Verbindung mit seinem Buch The C ++ Standard Library - Ein Tutorial und eine Referenz veröffentlicht . Die 184-Zeilen-Implementierung finden Sie hier .quelle
Ich habe die oben für libstdc ++ von Piotr Dobrogost vorgeschlagene Lösung ausprobiert und festgestellt, dass sie einen schmerzhaften Fehler aufweist: Aufgrund des Fehlens eines geeigneten Verschiebungskonstruktors für istream ist es sehr schwierig, das neu erstellte istream-Objekt aus der Erstellungsfunktion herauszuholen . Ein weiteres Problem dabei ist, dass ein FILE-Objekt verloren geht (auch wenn dies nicht der zugrunde liegende Posix-Dateideskriptor ist). Hier ist eine alternative Lösung, die diese Probleme vermeidet:
Der Aufruf von posix_fadvise () zeigt eine mögliche Verwendung. Beachten Sie auch, dass das Beispiel static_assert verwendet und C ++ 11 verwendet, außer dass es im C ++ 03-Modus einwandfrei erstellt werden sollte.
quelle
Nach meinem Verständnis gibt es im C ++ iostream-Objektmodell keine Zuordnung zu FILE-Zeigern oder Dateideskriptoren, um den Code portabel zu halten.
Trotzdem habe ich mehrere Stellen gesehen, die sich auf die mds-utils oder den Boost beziehen , um diese Lücke zu schließen.
quelle