Comment : utiliser la fonction ReadFile de Windows (Guide de programmation C#)
Cet exemple illustre la fonction ReadFile de Windows en lisant et affichant un fichier texte. La fonction ReadFile nécessite l'utilisation de code unsafe, car elle requiert un pointeur comme paramètre.
Le tableau d'octets passé à la fonction Read est un type managé. Cela signifie que le garbage collector de common language runtime (CLR) pourrait déplacer la mémoire utilisée par le tableau. Pour empêcher ceci, fixed est utilisé pour obtenir un pointeur vers la mémoire et le marquer afin que le garbage collector ne le déplace pas. À la fin du bloc fixed, la mémoire est automatiquement retournée à un état susceptible d'être soumis à parcourir le garbage collection.
Cette fonction est désignée par le terme « épinglage déclaratif ». L'épinglage est intéressant parce qu'il nécessite très peu de traitement supplémentaire sauf si une opération de garbage collection doit s'opérer sur le bloc fixed, ce qui est peu probable. Toutefois, l'épinglage peut mener à quelques effets secondaires indésirables pendant l'exécution du garbage collection global. La capacité du garbage collector de condenser la mémoire est limitée grandement par les mémoires tampons épinglées. Par conséquent, l'épinglage doit être évité si possible.
Exemple
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;
}
}
}
Voir aussi
Référence
Pointeurs et code unsafe (Guide de programmation C#)
Types pointeur (Guide de programmation C#)