Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Über die Ausnahmen hinaus, die bei jedem Methodenaufruf ausgelöst werden können (wie etwa eine OutOfMemoryException, wenn ein System unter Stress steht, oder eine NullReferenceException aufgrund eines Programmierfehlers), können Methoden des .NET-Dateisystems die folgenden Ausnahmen auslösen:
- System.IO.IOException, die Basisklasse aller System.IO Ausnahmetypen. Es wird für Fehler ausgelöst, deren Rückgabecodes vom Betriebssystem keinem anderen Ausnahmetyp direkt zugeordnet sind.
- System.IO.FileNotFoundException.
- System.IO.DirectoryNotFoundException.
- DriveNotFoundException.
- System.IO.PathTooLongException.
- System.OperationCanceledException.
- System.UnauthorizedAccessException.
- System.ArgumentException wird ausgelöst für ungültige Pfadzeichen im .NET Framework sowie in .NET Core 2.0 und früheren Versionen von .NET Core.
- System.NotSupportedException, die für ungültige Doppelpunkte in .NET Framework ausgelöst wird.
- System.Security.SecurityException, die für Anwendungen ausgelöst wird, die mit eingeschränkter Vertrauenswürdigkeit ausgeführt werden und denen lediglich die erforderlichen Berechtigungen für .NET Framework fehlen. (.NET Framework hat standardmäßig vollständiges Vertrauen.)
Zuordnen von Fehlercodes zu Ausnahmen
Da das Dateisystem eine Betriebssystemressource ist, schließen I/O-Methoden sowohl in .NET Core als auch .NET Framework Aufrufe an das zugrunde liegende Betriebssystem um. Wenn ein E/A-Fehler im vom Betriebssystem ausgeführten Code auftritt, gibt das Betriebssystem Fehlerinformationen an die .NET-E/A-Methode zurück. Die Methode übersetzt dann die Fehlerinformationen, in der Regel in Form eines Fehlercodes, in einen .NET-Ausnahmetyp. In den meisten Fällen erfolgt dies, indem der Fehlercode direkt in den entsprechenden Ausnahmetyp übersetzt wird; sie führt keine spezielle Zuordnung des Fehlers basierend auf dem Kontext des Methodenaufrufs durch.
Im Windows-Betriebssystem wird beispielsweise ein Methodenaufruf, der einen Fehlercode von ERROR_FILE_NOT_FOUND (oder 0x02) zurückgibt, einem FileNotFoundException zugeordnet, und ein Fehlercode von ERROR_PATH_NOT_FOUND (oder 0x03) wird einem DirectoryNotFoundException zugeordnet.
Allerdings sind die genauen Bedingungen, unter denen das Betriebssystem bestimmte Fehlercodes zurückgibt, häufig nicht dokumentiert oder schlecht dokumentiert. Daher können unerwartete Ausnahmen auftreten. Da Sie z. B. nicht mit einer Datei, sondern mit einem Verzeichnis arbeiten, würden Sie erwarten, dass das Übergeben eines ungültigen Verzeichnispfads an den DirectoryInfo-Konstruktor einen DirectoryNotFoundException auslöst. Es kann aber ebenso gut eine FileNotFoundException auslösen.
Ausnahmebehandlung in E/A-Vorgängen
Aufgrund dieses Rückgriffs auf das Betriebssystem können identische Ausnahmebedingungen (wie etwa der Fehler des nicht gefundenen Verzeichnisses in unserem Beispiel) dazu führen, dass eine E/A-Methode irgendeine aus der gesamten Klasse der E/A-Ausnahmen auslöst. Dies bedeutet, dass Ihr Code beim Aufrufen von E/A-APIs darauf vorbereitet sein sollte, die meisten oder alle diese Ausnahmen zu verarbeiten, wie in der folgenden Tabelle gezeigt:
| Ausnahmetyp | .NET Core/.NET 5+ | .NET Framework |
|---|---|---|
| IOException | Ja | Ja |
| FileNotFoundException | Ja | Ja |
| DirectoryNotFoundException | Ja | Ja |
| DriveNotFoundException | Ja | Ja |
| PathTooLongException | Ja | Ja |
| OperationCanceledException | Ja | Ja |
| UnauthorizedAccessException | Ja | Ja |
| ArgumentException | .NET Core 2.0 und früher | Ja |
| NotSupportedException | Nein | Ja |
| SecurityException | Nein | Nur eingeschränktes Vertrauen |
Fehlerbehandlung bei IOException
Als Basisklasse für Ausnahmen im System.IO Namespace wird IOException auch bei einem Fehlercode ausgelöst, der keinem vordefinierten Ausnahmetyp zugeordnet ist. Das bedeutet, dass sie von jedem E/A-Vorgang ausgelöst werden kann.
Von Bedeutung
Da IOException die Basisklasse der anderen Ausnahmetypen im Namespace System.IO ist, sollten Sie alle von der Basisklasse abgeleiteten Ausnahmen in einem catch Block behandeln, nachdem Sie die anderen I/O-bezogenen Ausnahmen behandelt haben.
Außerdem wurden mit .NET Core 2.1 die Überprüfungen zur Pfadkorrektheit entfernt (z. B. um sicherzustellen, dass keine ungültigen Zeichen in einem Pfad vorhanden sind), und die Laufzeit löst eine Ausnahme aus, die anhand eines Betriebssystemfehlercodes statt ihres eigenen Validierungscodes zugeordnet wird. Die wahrscheinlichste Ausnahme, die in diesem Fall ausgelöst wird, ist ein IOException, obwohl jeder andere Ausnahmetyp auch ausgelöst werden kann.
Beachten Sie, dass Sie in Ihrem Ausnahmebehandlungscode immer als Letztes die IOException behandeln sollten. Da sie die Basisklasse aller anderen EA-Ausnahmen bildet, werden sonst die Catch-Blöcke von abgeleiteten Klassen nicht ausgewertet.
Bei einem IOExceptionFehler können Sie zusätzliche Fehlerinformationen aus der IOException.HResult-Eigenschaft abrufen. Um den HResult-Wert in einen Win32-Fehlercode zu konvertieren, entfernen Sie die oberen 16 Bit des 32-Bit-Werts. In der folgenden Tabelle sind Fehlercodes aufgeführt, die möglicherweise in ein IOException eingebettet werden.
| HRESULT | Dauerhaft | BESCHREIBUNG |
|---|---|---|
| ERROR_SHARING_VIOLATION (Freigabeverletzung) | 32 | Der Dateiname fehlt, oder die Datei oder das Verzeichnis wird verwendet. |
| ERROR_FILE_EXISTS | 80 | Die Datei ist bereits vorhanden. |
| FEHLER_UNGÜLTIGER_PARAMETER | 87 | Ein argument, das an die Methode übergeben wird, ist ungültig. |
| FEHLER_BEREITS_VORHANDEN | 183 | Die Datei oder das Verzeichnis ist bereits vorhanden. |
Sie können diese mithilfe einer When-Klausel in einer catch-Anweisung behandeln, wie im folgenden Beispiel dargestellt.
using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
var sw = OpenStream(@".\textfile.txt");
if (sw is null)
return;
sw.WriteLine("This is the first line.");
sw.WriteLine("This is the second line.");
sw.Close();
}
static StreamWriter? OpenStream(string path)
{
if (path is null)
{
Console.WriteLine("You did not supply a file path.");
return null;
}
try
{
var fs = new FileStream(path, FileMode.CreateNew);
return new StreamWriter(fs);
}
catch (FileNotFoundException)
{
Console.WriteLine("The file or directory cannot be found.");
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("The file or directory cannot be found.");
}
catch (DriveNotFoundException)
{
Console.WriteLine("The drive specified in 'path' is invalid.");
}
catch (PathTooLongException)
{
Console.WriteLine("'path' exceeds the maximum supported path length.");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("You do not have permission to create this file.");
}
catch (IOException e) when ((e.HResult & 0x0000FFFF) == 32)
{
Console.WriteLine("There is a sharing violation.");
}
catch (IOException e) when ((e.HResult & 0x0000FFFF) == 80)
{
Console.WriteLine("The file already exists.");
}
catch (IOException e)
{
Console.WriteLine($"An exception occurred:\nError code: " +
$"{e.HResult & 0x0000FFFF}\nMessage: {e.Message}");
}
return null;
}
}
Imports System.IO
Module Program
Sub Main(args As String())
Dim sw = OpenStream(".\textfile.txt")
If sw Is Nothing Then Return
sw.WriteLine("This is the first line.")
sw.WriteLine("This is the second line.")
sw.Close()
End Sub
Function OpenStream(path As String) As StreamWriter
If path Is Nothing Then
Console.WriteLine("You did not supply a file path.")
Return Nothing
End If
Try
Dim fs As New FileStream(path, FileMode.CreateNew)
Return New StreamWriter(fs)
Catch e As FileNotFoundException
Console.WriteLine("The file or directory cannot be found.")
Catch e As DirectoryNotFoundException
Console.WriteLine("The file or directory cannot be found.")
Catch e As DriveNotFoundException
Console.WriteLine("The drive specified in 'path' is invalid.")
Catch e As PathTooLongException
Console.WriteLine("'path' exceeds the maximum supported path length.")
Catch e As UnauthorizedAccessException
Console.WriteLine("You do not have permission to create this file.")
Catch e As IOException When (e.HResult And &h0000FFFF) = 32
Console.WriteLine("There is a sharing violation.")
Catch e As IOException When (e.HResult And &h0000FFFF) = 80
Console.WriteLine("The file already exists.")
Catch e As IOException
Console.WriteLine($"An exception occurred:{vbCrLf}Error code: " +
$"{e.HResult And &h0000FFFF}{vbCrLf}Message: {e.Message}")
End Try
Return Nothing
End Function
End Module