我需要在原始模式下打开读取磁盘,因此我正在使用CreateFile API函数。
private static FileStream OpenDisk(string drive)
{
// Try to open hard disk drive in raw mode for reading
SafeFileHandle safeHandle = Native.CreateFile(
string.Format(@"\\.\{0}", drive),
FileAccess.Read,
FileShare.Read,
IntPtr.Zero,
FileMode.Open,
FileAttributes.ReadOnly | FileAttributes.Device,
IntPtr.Zero);
// Check if the drive was successfully opened
if (safeHandle.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
// Create file stream on the file for reading
return new FileStream(safeHandle, FileAccess.Read);
}
但是当我尝试从流中读取时,我收到以下错误
Handle does not support synchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened asynchronously (that is, it was opened explicitly for overlapped I/O).
以下是重现此问题的示例代码
using (FileStream stream = OpenDisk("X:"))
{
byte[] buffer = new byte[1000];
while (stream.Read(buffer, 0, 1000) > 0) { }
}
我真的不知道它对我有什么要求?当我使用更大的缓冲区(例如4096)时,它可以工作。当我说它工作时我的意思是它真的有效(总是),它工作了一段时间,直到我改变了缓冲区大小。我猜它里面有一些异步缓冲,当我指定更大的缓冲区然后默认缓冲大小它只是没用过,但是如何摆脱这个?
由于
更新
当我尝试使用BufferedStream读取它时,我遇到了同样的问题
using (BufferedStream stream = new BufferedStream(OpenDisk("X:"), 4096))
{
byte[] buffer = new byte[1000];
while (stream.Read(buffer, 0, 1000) > 0) { }
}
我是否了解BufferedStream的错误用途?它不应该读取和缓存指定大小的块吗?
答案 0 :(得分:4)
简而言之,来自卷的读取是非缓冲的,必须是整个扇区。缓冲区大小为4096实现了这一点。错误消息具有误导性,因为异步I / O和非缓冲往往会在一起。一些细节:
即使未在CreateFile中指定非高速缓存选项,也可以根据特定文件系统的判断将卷句柄打开为非高速缓存。您应该假设所有Microsoft文件系统都将未处理的卷句柄打开。对文件的非高速缓存I / O的限制也适用于卷。