使用.NET进行低级文件访问

时间:2015-03-06 14:08:40

标签: c# .net filesystems

.NET框架中是否有任何类提供对\。\ G: - 样式路径的访问。 (即原始卷)?

我们目前正在使用p /调用的ReadFile和WriteFile进行此操作,这对于同步访问并不复杂,但添加异步读/写是很繁琐的,因为所有关心你需要接管固定和处理OVERLAPPED结构并管理事件对象的生命周期等(即我们在Win32代码中必须做的所有繁琐工作......)

通过任何简单的测试技术,很难证明您与GC的交互也是正确的。

FileStream类包含所有这些代码,毫无疑问,它是一种完全防弹和精致的方式,并利用了许多我们无法使用的内部帮助程序。不幸的是,FileStream明确地阻止你打开原始卷,因此我们无法使用它。

框架中还有什么可以帮助避免从头开始编写这种代码吗?我在Reference Source中引用了一些内容,但没有任何消息传出来。

更新 - 我们已经尝试过以下建议,以避免通过自己打开设备并传入句柄来检查路径类型。当我们尝试这个时,会出现以下错误(请注意,此跟踪会通过FileStream的结构 - 即我们没有任何机会与流进行交互):

System.IO.IOException: The parameter is incorrect.

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.SeekCore(Int64 offset, SeekOrigin origin)
at System.IO.FileStream..ctor(SafeFileHandle handle, FileAccess access, Int32 bufferSize, Boolean isAsync)
at OurApp.USBComms.UsbDevice..ctor(Char driveLetter) in 

作为参考,我们的CreateFile调用如下所示:

var deviceName = String.Format(@"\\.\{0}:", driveLetter);

var handle = SafeNativeMethods.CreateFile(deviceName,
     0x80000000 | 0x40000000,
     FileShare.ReadWrite,
     0,
     FileMode.Open,
     (uint)FileOptions.Asynchronous | 0x20000000, // Last option is       'FILE_FLAG_NO_BUFFERING'
     IntPtr.Zero);
     if (handle.IsInvalid)
     {
        throw new IOException("CreateFile Error: " + Marshal.GetLastWin32Error());
     }

Update3:事实证明(无论如何在卷句柄上),你不能在用FILE_FLAG_OVERLAPPED打开的句柄上调用SetFilePointer。这是有道理的,因为SetFilePointer对于那些无论如何都有任何类型的多线程访问的文件都是无用的。不幸的是,FileStream似乎决定在构造过程中出于某种原因(仍然试图找出原因)调用它,这是导致失败的原因。

2 个答案:

答案 0 :(得分:3)

正如Sriram Sakthivel所说(+1),您可以将SafeFileHandle传递给FileStream构造函数。

从你的堆栈跟踪我假设你试图寻找一个无效位置的流;原始磁盘/卷有关于读/写位置的特殊规则。

例如,您无法在扇区中间开始读取磁盘(您必须读取/搜索每个512字节的块)。尝试在偏移0处读取以查看它是否更好。

答案 1 :(得分:2)

我相信您可以使用此constructor of FileStream将预先打开的FileHandle作为SafeFileHandle实例传递。有了这个,您可以使用托管FileStream实例来发出异步I / O操作。

public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync);

此外,当您计划执行异步I / O时,请不要忘记将isAsnc标志设置为true。否则you'll not get all the benefits of async I/O