共用方式為


HOW TO:使用 Windows ReadFile 函式 (C# 程式設計手冊)

更新:2007 年 11 月

此範例透過讀取和顯示文字檔示範 Windows ReadFile 函式。ReadFile 函式需要使用 unsafe 程式碼,因為必須要有指標做為參數。

傳遞到 Read 函式的位元組陣列為 Managed 型別。這表示 Common Language Runtime (CLR) 記憶體回收行程可依所需重新配置陣列使用的記憶體。為了避免這一點,fixed 會用來取得對記憶體的指標並加以標記,如此一來記憶體回收行程就不會移動它。在 fixed 區塊的結尾,記憶體會自動回到遵從記憶體回收行程的移動。

這項功能稱為「宣告式固定」(Declarative Pinning)。固定的好處在於虛耗的空間很少,除非記憶體回收發生在 fixed 區塊內,但實際上會發生的機率很低。不過,固定可能在全域記憶體回收執行時,導致某些不想要的副作用。記憶體回收行程壓縮記憶體的功能會大幅度受到固定緩衝區的限制。因此,應盡量避免使用固定。

範例

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

請參閱

概念

C# 程式設計手冊

參考

Unsafe 程式碼和指標 (C# 程式設計手冊)

指標型別 (C# 程式設計手冊)

其他資源

C# 參考

記憶體回收