Getting a HANDLE from a std::ofstream
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.
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.
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.
No. You can't even get at the FILE*
(or _Filet*
as it's internally known) inside std::basic_filebuf
.
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<>
.
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);
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.
精彩评论