Share via


Cómo: Utilizar la función ReadFile de Windows (Guía de programación de C#)

Actualización: noviembre 2007

Este ejemplo muestra la función de Windows ReadFile que lee y muestra un archivo de texto. La función ReadFile requiere el uso de código unsafe porque requiere un puntero como parámetro.

La matriz de bytes pasada a la función Read es un tipo administrado. Esto significa que el recolector de elementos no utilizados de Common Language Runtime (CLR) puede reubicar la memoria usada por la matriz según lo considere necesario. Para evitar esto, se utiliza fixed para obtener un puntero a la memoria y marcarlo para que no lo mueva el recolector de elementos no utilizados. Al final del bloque fixed, la memoria vuelve automáticamente a estar sujeta a moverse a través de la recolección de elementos no utilizados.

Esta capacidad se conoce como anclaje declarativo. Con el anclaje apenas hay carga de ejecución, a menos que se produzca una recolección de elementos no utilizados en el bloque fixed, lo cual no es probable que suceda. Sin embargo, el anclaje puede producir algunos efectos secundarios no deseados durante la ejecución de la recolección de elementos no utilizados global. Los búferes anclados limitan considerablemente la capacidad del recolector de elementos no utilizados para compactar la memoria. Por consiguiente, el anclaje debería evitarse si es posible.

Ejemplo

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

Vea también

Conceptos

Guía de programación de C#

Referencia

Código no seguro y punteros (Guía de programación de C#)

Tipos de puntero (Guía de programación de C#)

Otros recursos

Referencia de C#

Recolección de elementos no utilizados