Neu in .NET 6 [14]: Direkte Dateizugriffe ohne Stream-Objekte

Der Dotnet-Doktor Holger Schwichtenberg  –  1 Kommentare

Die Serie zu den Neuerungen in .NET 6 behandelt im vierzehnten Teil die Klasse System.IO.RandomAccess.

.NET 6 bietet eine neue Klasse System.IO.RandomAccess für den Dateisystemzugriff, die performanter ist als die bisherigen Zugriffe mit Stream-Objekten.

Das folgende Listing zeigt die neue Klasse im Einsatz beim Schreiben einer Datei mit Write() und beim Lesen mit Read().

public static void FileIOWithoutStream()
{
var path = System.IO.Path.GetTempFileName();

#region ------- Dateiinhalte schreiben ohne Stream-Objekte
using (Microsoft.Win32.SafeHandles.SafeFileHandle handle
= File.OpenHandle(path, FileMode.Create,
FileAccess.Write))
{
var arr = new byte[100];
arr = Encoding.ASCII.GetBytes("1234567890abcdef" +
"1234567890abcdef1234567890abcdef" +
"1234567890abcdef1234567890abcdef" +
"1234567890abcdef1234567890abcdef" +
"1234567890abcdef1234567890abcdef");
int startpos = 00;
Span<byte> buffer = arr;

RandomAccess.Write(handle, buffer, startpos);

handle.Close();
}
#endregion

#region ------- Dateiinhalte lesen ohne Stream-Objekte
using (Microsoft.Win32.SafeHandles.SafeFileHandle handle
= File.OpenHandle(path))
{

// Dateilänge ermitteln
long length = RandomAccess.GetLength(handle);
Console.WriteLine(length);

// 100 Bytes einlesen, erste 10 Zeichen überspringen
var arr = new byte[100];
int startpos = 10;
Span<byte> buffer = arr;
var bytesRead = RandomAccess.Read(handle, buffer, startpos);

Console.WriteLine("Puffergröße: " + buffer.Length);
Console.WriteLine("Eingelesene Bytes: " + bytesRead);
Console.WriteLine("Inhalte an Position 1:"
+ (char)arr[0]); // a
Console.WriteLine("Inhalte an Position 11:"
+ (char)arr[10]); // 5
Console.WriteLine("Inhalte an Position 99:"
+ (char)arr[98]); // c

handle.Close();
}
#endregion
}

In einem Leistungsvergleich für das sequentielle Schreiben einer Datei mit 100 MB Inhalt ist RandomAccess.Write() schneller als die Nutzung von Stream-Objekten, aber die Methode WriteAllBytes() liegt noch vor RandomAccess.Write().

Geschwindigkeit beim Schreiben einer 100-MB großen Datei
Geschwindigkeit beim Schreiben einer 100-MB großen Datei

Das erklärt sich leider nicht beim Blick in die Dokumentation, sondern nur, wenn man sich die Mühe macht, den Quellcode von WriteAllBytes() in .NET 6 mit der Implementierung vorher (.NET 5) zu vergleichen. Dann sieht man, dass WriteAllBytes() nun intern System.IO.RandomAccess und damit auch andere Betriebssystem-APIs verwendet.

WriteAllBytes() in .NET 5 und .NET 6
WriteAllBytes() in .NET 5 und .NET 6