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.
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.
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.
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.
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.
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.
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*
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.
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*.
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++.
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; }
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; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With