Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to construct a c++ fstream from a POSIX file descriptor?

I'm basically looking for a C++ version of fdopen(). I did a bit of research on this and it is one of those things that seems like it should be easy, but turns out to be very complicated. Am I missing something in this belief (i.e. it really is easy)? If not, is there a good library out there somewhere to handle this?

EDIT: Moved my example solution to a separate answer.

like image 995
BD at Rivenhill Avatar asked Apr 30 '10 16:04

BD at Rivenhill


People also ask

What is a file descriptor C++?

A file descriptor is a number that uniquely identifies an open file in a computer's operating system. It describes a data resource, and how that resource may be accessed. When a program asks to open a file — or another data resource, like a network socket — the kernel: Grants access.

What library is fstream in C++?

fstream Library: Fstream is a library that consists of both, ofstream and ifstream which means it can create files, write information to files, and read information from files. This header file is generally used as a data type that represents the file stream.

What is the default mode operator of fstream?

The default mode of ifstream is in . The default mode of ofstream is out . That's why they're named that way. fstream has no default mode.

Is iostream included in fstream?

An iostream is a stream which you can write to and read from, you probably won't be using them much on their own. An fstream is an iostream which writes to and reads from a file. So: every fstream is an iostream but not every iostream is an fstream.

Is there a way to create a fstream function in C++?

AFAIK, there is no way to do this in standard C++. Depending on your platform, your implementation of the standard library may offer (as a nonstandard extension) a fstream constructor taking a file descriptor (This is the case for libstdc++, IIRC) or a FILE* as an input.

Is there a non-standard version of ifstream's constructor taking POSIX file descriptor?

There used to be non-standard version of ifstream's constructor taking POSIX file descriptor but it's missing both from current docs and from code. There is another non-standard version of ifstream's constructor taking FILE*

How to use iostream instead of fstream?

You can go the other way: implement your own stream buffer that wraps a file descriptor and then use it with iostream instead of fstream. Using Boost.Iostreams can make the task easier.

Is there a way to use a file descriptor in C++?

AFAIK, there is no way to do this in standard C++. Depending on your platform, your implementation of the standard library may offer (as a nonstandard extension) a fstream constructor taking a file descriptor as input. (This is the case for libstdc++, IIRC) or a FILE*.


1 Answers

From the answer given by Éric Malenfant:

AFAIK, there is no way to do this in standard C++. Depending on your platform, your implementation of the standard library may offer (as a nonstandard extension) a fstream constructor taking a file descriptor as input. (This is the case for libstdc++, IIRC) or a FILE*.

Based on above observations and my research below there's working code in two variants; one for libstdc++ and another one for Microsoft Visual C++.


libstdc++

There's non-standard __gnu_cxx::stdio_filebuf class template which inherits std::basic_streambuf and has the following constructor

stdio_filebuf (int __fd, std::ios_base::openmode __mode, size_t __size=static_cast< size_t >(BUFSIZ))  

with description This constructor associates a file stream buffer with an open POSIX file descriptor.

We create it passing POSIX handle (line 1) and then we pass it to istream's constructor as basic_streambuf (line 2):

#include <ext/stdio_filebuf.h> #include <iostream> #include <fstream> #include <string>  using namespace std;  int main() {     ofstream ofs("test.txt");     ofs << "Writing to a basic_ofstream object..." << endl;     ofs.close();      int posix_handle = fileno(::fopen("test.txt", "r"));      __gnu_cxx::stdio_filebuf<char> filebuf(posix_handle, std::ios::in); // 1     istream is(&filebuf); // 2      string line;     getline(is, line);     cout << "line: " << line << std::endl;     return 0; } 

Microsoft Visual C++

There used to be non-standard version of ifstream's constructor taking POSIX file descriptor but it's missing both from current docs and from code. There is another non-standard version of ifstream's constructor taking FILE*

explicit basic_ifstream(_Filet *_File)     : _Mybase(&_Filebuffer),         _Filebuffer(_File)     {   // construct with specified C stream     } 

and it's not documented (I couldn't even find any old documentation where it would be present). We call it (line 1) with the parameter being the result of calling _fdopen to get C stream FILE* from POSIX file handle.

#include <cstdio> #include <iostream> #include <fstream> #include <string>  using namespace std;  int main() {     ofstream ofs("test.txt");     ofs << "Writing to a basic_ofstream object..." << endl;     ofs.close();      int posix_handle = ::_fileno(::fopen("test.txt", "r"));      ifstream ifs(::_fdopen(posix_handle, "r")); // 1      string line;     getline(ifs, line);     ifs.close();     cout << "line: " << line << endl;     return 0; } 
like image 185
Piotr Dobrogost Avatar answered Sep 18 '22 17:09

Piotr Dobrogost