关于C ++:从std :: ofstream获取句柄

Getting a HANDLE from a std::ofstream

是否可以从std :: ofstream(Visual C ++ 2005)获取基础文件HANDLE?

这与这个问题相反:

我可以使用CreateFile,但将句柄强制放入std :: ofstream吗?

我想要这样做的原因是修改文件的属性(例如创建时间),而不必使用CreateFile打开文件。


C ++标准没有提供任何方法来指定或检索ofstream的原始文件描述符,因此我认为这是不可能的。但是,可能会建立一个自定义的streambuf类,该类实现往返于HANDLE的流缓冲,然后定义一个使用该缓冲区的自定义ostream类型。我不确定这是否是您真正要寻找的东西,但这是一个可行的选择。


我的回答应以"我是Unix开发人员,而不是Windows开发人员"开头。但是我遇到了与您相同的问题,这就是我选择解决的方法。我希望有一个更好的答案。我在下面的回答将使您的皮肤爬行,但确实有效。

首先,我们需要fdbuf中的_Filet *。这是一个私有成员,因此我们不能仅创建一个使我们对其具有可见性的新类。因此,我修改了fstream的标头,以便在filebuf中添加一个新的朋友函数,这样特定的函数将让我们作弊并获得对该成员的访问权限(我将其添加到" _Filet * _Myfile;"的定义下方):

1
 friend HANDLE __HACK_getFilebufHANDLE(filebuf*);

现在我们有一个公共功能来访问私人成员。第二步是编写函数:

1
2
3
4
5
namespace std {
   HANDLE __HACK_getFilebufHANDLE(filebuf*in) {
      return (HANDLE) _get_osfhandle(_fileno(in->_Myfile));
   }
};

最后,只需要调用它,除了rdbuf返回错误的类型(iobuf而不是filebuf)。由于我们已经在整个过程中"无所不能",因此我们不妨使每个人的皮肤都爬行(但在现实生活中,请在此处进行类型检查以验证对派生类型的转换):

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

抱歉,我没有更干净的答案。


在标准C ++中这是不可能的。但是,使用Boost.IOStreams库并不难。创建一个Device,将其包装在boost::iostreams::stream_buffer<>中,并使用boost::iostreams::stream<>添加适当的流。


不。您甚至无法获得std::basic_filebuf内部的FILE*(或内部称为_Filet*)。


不,我尝试了很多方法。
这行:"std::ifstream ifs(fh);"在某些msvs中可能不会起作用,例如2008。

我找到了另一种方法,您可以在进程中枚举句柄,并找到释放到文件名的句柄。

这样,我就掌握了。


使用VisualC ++ 2010库,以下应该可以工作。我认为对于VisualC ++ 2005来说是相同的,但是您必须验证:

1
2
3
4
5
6
7
8
9
10
11
12
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);