6

Is it possible to get the underlying file HANDLE from a std::ofstream (Visual C++ 2005)?

This is the opposite of this question:

Can I use CreateFile, but force the handle into a std::ofstream?

The reason I want to so this is to modify attributes of the file (e.g. creation time) without having to open the file with CreateFile.

Community
  • 1
  • 1
mpipe3
  • 1,013
  • 1
  • 9
  • 20
  • The standard library is, well, standard, so it has no idea what your operating system and cannot provide functionality accordingly; it has to work everywhere. So the answer is no in C++, but possibly yes in non-standard C++; I don't know if the latter is an option either, you may have to just go the "long" way, but I wanted to make sure that was clear. – GManNickG Feb 04 '11 at 08:51
  • I was happy to use a solution that only worked in Visual C++ – mpipe3 Feb 06 '11 at 18:28

6 Answers6

6

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.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
5

My answer should be prefaced with "I am a Unix developer, not a Windows developer." But I had the same problem that you did, and this is how I chose to address it. I would love to have a better answer. My answer below will make your skin crawl, but it worked.

First off, we'll need the _Filet* from the fdbuf. This is a private member, so we can't just create a new class that gives us visibility into it. So, I modify the header for fstream to add a new friend function in filebuf, so that the specific function will let us cheat and get access to that member (I added it just below the definition "_Filet *_Myfile;"):

 friend HANDLE __HACK_getFilebufHANDLE(filebuf*);

Now we have a public function to access the private member. Step two is to write the function:

namespace std {
   HANDLE __HACK_getFilebufHANDLE(filebuf*in) {
      return (HANDLE) _get_osfhandle(_fileno(in->_Myfile));
   }
};

Lastly, you just need to call it, except that rdbuf returns the wrong type (iobuf rather than filebuf). Since we're already off in "here there be dragons" for this entire process, we may as well make everyone's skin crawl (but in real life, do type checking here to validate the cast to the derived type):

  __HACK_getFilebufHANDLE((filebuf*)fopoutstrm.rdbuf())

Sorry that I don't have a cleaner answer.

Lee
  • 51
  • 1
  • 1
1

No. You can't even get at the FILE* (or _Filet* as it's internally known) inside std::basic_filebuf.

MSalters
  • 173,980
  • 10
  • 155
  • 350
1

This is not possible in standard C++. However, with Boost.IOStreams library it is not that hard. Create a Device, wrap it in a boost::iostreams::stream_buffer<> and add appropriate stream using boost::iostreams::stream<>.

wilx
  • 17,697
  • 6
  • 59
  • 114
0

With the VisualC++ 2010 libraries, the following should work. I assume it's the same for VisualC++ 2005, but you will have to verify:

FILE* fh = fopen(...);

HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fh));
// do something on hFile

// create iostream from FILE
std::ifstream ifs(fh);

// use it...

// close FILE
_close(fh);
Daniel Gehriger
  • 7,339
  • 2
  • 34
  • 55
  • 1
    `std::ifstream` has no such constructor. Is this an extension or wild guess? – GManNickG Feb 04 '11 at 09:32
  • 1
    It's an (undocumented!) extension on VC10 -- I don't know about VC2005, though, but I assume it's there, too. If the OP needs a future-proof solution, I'd also implement a custom streambuf, as suggested by @templatetypedef. – Daniel Gehriger Feb 04 '11 at 09:35
  • Okay. You should mention that this only works on VC10 as an extension to your answer, then. – GManNickG Feb 04 '11 at 09:45
  • That solves half the problem, ie FILE* -> HANDLE but I was looking for a way to get from ofstream -> HANDLE. In the code where I wanted to use this I only have the ofstream. – mpipe3 Feb 06 '11 at 18:30
  • @mpipe3: I see. I don't think it's possible then. There isn't a public interface to retrieve the FILE handle. – Daniel Gehriger Feb 06 '11 at 19:57
  • It is recommended to match the `fopen` and `fclose` – QT-1 Apr 24 '22 at 11:53
0

No. I try many ways. this line: "std::ifstream ifs(fh);" may not wrok in some msvs, such as 2008.

I find another way, you can enumerate handle in your process, and find the handle that releated to the filename.

In this way, I get the handle.

Sam Young
  • 1
  • 1
  • Could you perhaps explain *how* to enumerate the handles in the process and find the one that relates to the filename? – Nick Dec 07 '18 at 03:15