如何获取Stream的底层文件句柄?

时间:2011-12-27 02:27:19

标签: c# .net stream seek

我有一个适用于物理内存快照的应用程序(例如,VMware VMEM文件)。除此之外,它还可以通过虚拟而非物理地址从快照中读取进程/模块。这涉及通过页表一次重建4KB模块,这反过来意味着对Stream的Seek()方法的 lot 调用。

由于我不确定的原因,这些对Seek()的调用使事情陷入困境。因此,我正在寻找一种解决方法 - 或者至少是围绕托管Seek()实现的方法。我最好的猜测是PInvoke SetFilePointer并直接使用它,但为了做到这一点,我需要为Stream获取IntPtr / SafeFileHandle。我有一些限制:

  1. 我正在使用的API仅限于.NET 3.5,所以不幸的是MemoryMappedFile不是一个选项。

  2. 我不能使用FileStream(已经有可以通过反射访问的私有SafeFileHandle字段)或PInvoke CreateFile()以另一种方式获取快照 - 该API包含一个BinaryReader,它具有对快照的独占锁定。

  3. 当然,与FileStream不同,BinaryReader及其底层Stream都没有对文件句柄的引用。但肯定必须存在一个?在这种情况下,我该如何获取它?

2 个答案:

答案 0 :(得分:4)

Stream没有文件句柄,因为它是一个抽象类。实现Stream的类可能会也可能不会使用文件句柄 - FileStream,因为它从文件中读取数据,但是MemoryStream例如不会。

要获取其SafeFileHandleBinaryReader的{​​{1}}的基础文件句柄(在本例中为Stream),请使用反射来访问FileStream ,像这样:

private SafeFileHandle _handle

旁注:在这种情况下,直接拨打SafeFileHandle sfh = (SafeFileHandle)typeof(FileStream).GetField("_handle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue((FileStream)YOUR_BINARY_READER.BaseStream) SetFilePointer()都没有帮助。似乎没有快速的方法来处理使用它的卷(数百万个连续呼叫)的随机磁盘访问。

答案 1 :(得分:1)

由于BinaryReader超过FileStream,您可以访问阅读器的BaseStream,将其转换为FileStream,然后使用其公共SafeFileHandle属性进入手柄。像这样:

FileStream stream = (FileStream)(reader.BaseStream);
//use stream.SafeFileHandle