更新:2007 年 11 月
下面的示例通过读取并显示一个文本文件来演示 Windows ReadFile 函数。ReadFile 函数需要使用 unsafe 代码,因为它需要一个作为参数的指针。
传递到 Read 函数的字节数组是托管类型。这意味着公共语言运行时 (CLR) 垃圾回收器可能会随意地对数组使用的内存进行重新定位。为了防止出现这种情况,使用
此功能称为“声明式锁定”。使用锁定,系统开销会非常小,除非在 fixed 块中发生垃圾回收(但此情况不太可能发生)。但是,锁定会在全局垃圾回收运行过程中导致某些不利的副作用。垃圾回收器压缩内存的能力在很大程度上受到锁定缓冲区的限制。因此,应尽可能避免使用锁定。
示例
C# | 复制代码 |
---|---|
class FileReader { const uint GENERIC_READ = 0x80000000; const uint OPEN_EXISTING = 3; System.IntPtr handle; [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)] static extern unsafe System.IntPtr CreateFile ( string FileName, // file name uint DesiredAccess, // access mode uint ShareMode, // share mode uint SecurityAttributes, // Security Attributes uint CreationDisposition, // how to create uint FlagsAndAttributes, // file attributes int hTemplateFile // handle to template file ); [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] static extern unsafe bool ReadFile ( System.IntPtr hFile, // handle to file void* pBuffer, // data buffer int NumberOfBytesToRead, // number of bytes to read int* pNumberOfBytesRead, // number of bytes read int Overlapped // overlapped buffer ); [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] static extern unsafe bool CloseHandle ( System.IntPtr hObject // handle to object ); public bool Open(string FileName) { // open the existing file for reading handle = CreateFile ( FileName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0 ); if (handle != System.IntPtr.Zero) { return true; } else { return false; } } public unsafe int Read(byte[] buffer, int index, int count) { int n = 0; fixed (byte* p = buffer) { if (!ReadFile(handle, p + index, count, &n, 0)) { return 0; } } return n; } public bool Close() { return CloseHandle(handle); } } class Test { static int Main(string[] args) { if (args.Length != 1) { System.Console.WriteLine("Usage : ReadFile <FileName>"); return 1; } if (!System.IO.File.Exists(args[0])) { System.Console.WriteLine("File " + args[0] + " not found."); return 1; } byte[] buffer = new byte[128]; FileReader fr = new FileReader(); if (fr.Open(args[0])) { // Assume that an ASCII file is being read. System.Text.ASCIIEncoding Encoding = new System.Text.ASCIIEncoding(); int bytesRead; do { bytesRead = fr.Read(buffer, 0, buffer.Length); string content = Encoding.GetString(buffer, 0, bytesRead); System.Console.Write("{0}", content); } while (bytesRead > 0); fr.Close(); return 0; } else { System.Console.WriteLine("Failed to open requested file"); return 1; } } } |