【问题标题】:Getting a HANDLE from a std::ofstream从 std::ofstream 获取 HANDLE
【发布时间】:2011-02-04 08:46:56
【问题描述】:

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

这与这个问题相反:

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

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

【问题讨论】:

  • 标准库是标准库,所以它不知道您的操作系统是什么,也无法提供相应的功能;它必须在任何地方工作。所以答案在 C++ 中是否定的,但在非标准 C++ 中可能是肯定的;我不知道后者是否也是一种选择,您可能不得不走“很长”的路,但我想确保这一点很清楚。
  • 我很高兴使用仅适用于 Visual C++ 的解决方案

标签: c++ winapi


【解决方案1】:

C++ 标准没有提供任何方法来指定或检索ofstream 的原始文件描述符,所以我认为这是不可能的。然而, 可能是构建一个自定义的streambuf 类来实现与HANDLE 之间的流缓冲,然后定义一个使用该缓冲区的自定义ostream 类型。我不确定这是否真的是您想要的,但这是一个可行的选择。

【讨论】:

    【解决方案2】:

    我的回答应该以“我是 Unix 开发人员,而不是 Windows 开发人员”开头。但是我遇到了和你一样的问题,这就是我选择解决它的方式。我很想有一个更好的答案。我在下面的回答会让你皮肤发痒,但它奏效了。

    首先,我们需要来自 fdbuf 的 _Filet*。这是一个私有成员,所以我们不能只创建一个新类来让我们看到它。所以,我修改了 fstream 的头文件以在 filebuf 中添加一个新的朋友函数,这样特定的函数就可以让我们作弊并访问该成员(我在定义“_Filet *_Myfile;”下面添加了它):

     friend HANDLE __HACK_getFilebufHANDLE(filebuf*);
    

    现在我们有了一个访问私有成员的公共函数。第二步,编写函数:

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

    最后,你只需要调用它,除了 rdbuf 返回错误的类型(iobuf 而不是 filebuf)。由于我们已经在整个过程中“这里有龙”,我们不妨让每个人的皮肤爬行(但在现实生活中,在这里进行类型检查以验证对派生的演员表类型):

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

    抱歉,我没有更清晰的答案。

    【讨论】:

      【解决方案3】:

      没有。您甚至无法访问std::basic_filebuf 内部的FILE*(或内部已知的_Filet*)。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          没有。我尝试了很多方法。 此行:"std::ifstream ifs(fh);" 在某些 msv 中可能无法正常工作,例如 2008。

          我找到另一种方法,你可以在你的进程中枚举句柄,并找到与文件名相关的句柄。

          这样,我搞定了。

          【讨论】:

          • 您能否解释一下如何枚举进程中的句柄并找到与文件名相关的句柄?
          【解决方案6】:

          使用 VisualC++ 2010 库,以下应该可以工作。我认为 VisualC++ 2005 也是如此,但您必须验证:

          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);
          

          【讨论】:

          • std::ifstream 没有这样的构造函数。这是扩展还是胡乱猜测?
          • 它是 VC10 上的一个(未记录的!)扩展——虽然我不知道 VC2005,但我认为它也在那里。如果 OP 需要一个面向未来的解决方案,我还会按照 @templatetypedef 的建议实现一个自定义的 streambuf。
          • 好的。您应该提到,这仅适用于 VC10,作为您答案的扩展。
          • 解决了一半的问题,即 FILE* -> HANDLE,但我正在寻找一种从 ofstream -> HANDLE 获取的方法。在我想使用它的代码中,我只有 ofstream。
          • @mpipe3:我明白了。我认为那是不可能的。没有用于检索 FILE 句柄的公共接口。
          猜你喜欢
          • 2010-09-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-06
          • 1970-01-01
          • 2020-11-05
          • 2017-08-10
          相关资源
          最近更新 更多