Retrieving file descriptor from a std::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.
Non-portable gcc solution is:
#include <ext/stdio_filebuf.h>
{
int fd = ...;
__gnu_cxx::stdio_filebuf<char> fd_file_buf{fd, std::ios_base::out | std::ios_base::binary};
std::ostream fd_stream{&fd_file_buf};
// Write into fd_stream.
// ...
// Flushes the stream and closes fd at scope exit.
}
How to open an ifstream from a file descriptor?
Short answer: you can't, not in standard C++ anyway. There is no official/portable way to do it.
You can, however, find some "work-around" solutions in these previous posts:
How to construct a c++ fstream from a POSIX file descriptor?
Getting a FILE* from a std::fstream
Retrieving file descriptor from a std::fstream
Getting a FILE* from a std::fstream
The short answer is no.
The reason, is because the std::fstream
is not required to use a FILE*
as part of its implementation. So even if you manage to extract file descriptor from the std::fstream
object and manually build a FILE object, then you will have other problems because you will now have two buffered objects writing to the same file descriptor.
The real question is why do you want to convert the std::fstream
object into a FILE*
?
Though I don't recommend it, you could try looking up funopen()
.
Unfortunately, this is not a POSIX API (it's a BSD extension) so its portability is in question. Which is also probably why I can't find anybody that has wrapped a std::stream
with an object like this.
FILE *funopen(
const void *cookie,
int (*readfn )(void *, char *, int),
int (*writefn)(void *, const char *, int),
fpos_t (*seekfn) (void *, fpos_t, int),
int (*closefn)(void *)
);
This allows you to build a FILE
object and specify some functions that will be used to do the actual work. If you write appropriate functions you can get them to read from the std::fstream
object that actually has the file open.
How to get file id from std::ofstream
There is no standard way to get a file descriptor from a standard fstream. There may be a platform specific method, depending on your standard library implementation.
If you're using libstdc++ then according to this there may be a filedesc()
method on the fstream object that gives you what you want.
Getting a HANDLE from a std::ofstream
The C++ standard does not provide any means for specifying or retrieving the raw file descriptors of an ofstream
, so I don't believe this is possible. What is possible, though, would be to build a custom streambuf
class that implements stream buffering to and from a HANDLE
, then to define a custom ostream
type that uses that buffer. I'm not sure if that's really what you're looking for, but it is a viable option.
Handle socket descriptors like file descriptor (fstream)? C++/Linux
The standard file stream doesn't support use of a file descriptor. However, the I/O stream classes make it reasonably easy to create your own abstraction which allows creating your own sources of or destination for characters. The magic class is std::streambuf
whose responsibility is to buffer characters and read or write characters at appropriate times. Nicolai Josuttis's "The C++ Standard Library" has a detailed description of how to do so (the basis of which I contributed to Nico many years ago). A simple implementation of a stream buffer using a socket for reading and writing would look something like this:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <streambuf>
#include <cstddef>
#include <unistd.h>
class fdbuf
: public std::streambuf
{
private:
enum { bufsize = 1024 };
char outbuf_[bufsize];
char inbuf_[bufsize + 16 - sizeof(int)];
int fd_;
public:
typedef std::streambuf::traits_type traits_type;
fdbuf(int fd);
~fdbuf();
void open(int fd);
void close();
protected:
int overflow(int c);
int underflow();
int sync();
};
fdbuf::fdbuf(int fd)
: fd_(-1) {
this->open(fd);
}
fdbuf::~fdbuf() {
this->close();
}
void fdbuf::open(int fd) {
this->close();
this->fd_ = fd;
this->setg(this->inbuf_, this->inbuf_, this->inbuf_);
this->setp(this->outbuf_, this->outbuf_ + bufsize - 1);
}
void fdbuf::close() {
if (!(this->fd_ < 0)) {
this->sync();
::close(this->fd_);
}
}
int fdbuf::overflow(int c) {
if (!traits_type::eq_int_type(c, traits_type::eof())) {
*this->pptr() = traits_type::to_char_type(c);
this->pbump(1);
}
return this->sync() == -1
? traits_type::eof()
: traits_type::not_eof(c);
}
int fdbuf::sync() {
if (this->pbase() != this->pptr()) {
std::streamsize size(this->pptr() - this->pbase());
std::streamsize done(::write(this->fd_, this->outbuf_, size));
// The code below assumes that it is success if the stream made
// some progress. Depending on the needs it may be more
// reasonable to consider it a success only if it managed to
// write the entire buffer and, e.g., loop a couple of times
// to try achieving this success.
if (0 < done) {
std::copy(this->pbase() + done, this->pptr(), this->pbase());
this->setp(this->pbase(), this->epptr());
this->pbump(size - done);
}
}
return this->pptr() != this->epptr()? 0: -1;
}
int fdbuf::underflow()
{
if (this->gptr() == this->egptr()) {
std::streamsize pback(std::min(this->gptr() - this->eback(),
std::ptrdiff_t(16 - sizeof(int))));
std::copy(this->egptr() - pback, this->egptr(), this->eback());
int done(::read(this->fd_, this->eback() + pback, bufsize));
this->setg(this->eback(),
this->eback() + pback,
this->eback() + pback + std::max(0, done));
}
return this->gptr() == this->egptr()
? traits_type::eof()
: traits_type::to_int_type(*this->gptr());
}
int main()
{
fdbuf inbuf(0);
std::istream in(&inbuf);
fdbuf outbuf(1);
std::ostream out(&outbuf);
std::copy(std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(out));
}
How to Access File Descriptor of Open File
If you're trying to get to the FILE* from the stream then the answer is basically "you can't" as stated by more enlightened people than me here.
Related Topics
Getting "Source Type Is Not Polymorphic" When Trying to Use Dynamic_Cast
How to Create a Sparse Array in C++
How to Dynamically Allocate a Matrix
Is F(Void) Deprecated in Modern C and C++
C++11: Compile Time Calculation of Array
C++ Data Alignment /Member Order & Inheritance
Sse, Intrinsics, and Alignment
Why Is There No Transform_If in the C++ Standard Library
What Is Decltype with Two Arguments
Do Rvalue References Allow Dangling References
What Is Going on with 'Gets(Stdin)' on the Site Coderbyte
Which Std::Async Implementations Use Thread Pools
How to Use C++ with Objective-C in Xcode
Why Does Calling Method Through Null Pointer "Work" in C++
How to Implement a Natural Sort Algorithm in C++
Error: Cannot Bind Non-Const Lvalue Reference of Type 'Int&' to an Rvalue of Type 'Int'