Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Oprócz wyjątków, które mogą być zgłaszane w dowolnym wywołaniu metody (np OutOfMemoryException . gdy system jest zestresowany lub NullReferenceException z powodu błędu programisty), metody systemu plików .NET mogą zgłaszać następujące wyjątki:
- System.IO.IOException, klasa bazowa wszystkich System.IO typów wyjątków. Jest zgłaszany w przypadku błędów, których kody powrotne z systemu operacyjnego nie są bezpośrednio mapowane na żaden inny typ wyjątku.
- System.IO.FileNotFoundException.
- System.IO.DirectoryNotFoundException.
- DriveNotFoundException.
- System.IO.PathTooLongException.
- System.OperationCanceledException.
- System.UnauthorizedAccessException.
- System.ArgumentException, który jest zgłaszany w przypadku nieprawidłowych znaków ścieżki w programie .NET Framework oraz na platformie .NET Core 2.0 i we wcześniejszych wersjach.
- System.NotSupportedException, który jest zgłaszany dla nieprawidłowego użycia dwukropków w .NET Framework.
- System.Security.SecurityException, który jest zgłaszany w przypadku aplikacji działających w ograniczonym zaufaniu, które nie mają niezbędnych uprawnień tylko na platformie .NET Framework. (Pełne zaufanie jest ustawieniem domyślnym w programie .NET Framework).
Mapowanie kodów błędów na wyjątki
Ponieważ system plików jest zasobem systemu operacyjnego, metody we/wy w programach .NET Core i .NET Framework opakowuje wywołania do bazowego systemu operacyjnego. Gdy w kodzie wykonywanym przez system operacyjny wystąpi błąd we/wy, system operacyjny zwraca informacje o błędzie do metody we/wy platformy .NET. Następnie metoda tłumaczy informacje o błędzie, zazwyczaj w postaci kodu błędu, na typ wyjątku platformy .NET. W większości przypadków wykonuje to przez bezpośrednie tłumaczenie kodu błędu na odpowiadający mu typ wyjątku; nie wykonuje żadnego specjalnego mapowania błędu na podstawie kontekstu wywołania metody.
Na przykład w systemie operacyjnym Windows wywołanie metody zwracające kod błędu ERROR_FILE_NOT_FOUND (lub 0x02) mapuje na FileNotFoundException, a kod błędu ERROR_PATH_NOT_FOUND (lub 0x03) mapuje na DirectoryNotFoundException.
Jednak dokładne warunki, w których system operacyjny zwraca określone kody błędów, są często nieudokumentowane lub źle udokumentowane. W rezultacie mogą wystąpić nieoczekiwane wyjątki. Na przykład, ponieważ pracujesz z katalogiem, a nie z plikiem, można oczekiwać, że podanie nieprawidłowej ścieżki katalogu do DirectoryInfo konstruktora zgłasza błąd DirectoryNotFoundException. Może jednak również zgłosić wartość FileNotFoundException.
Obsługa wyjątków w operacjach we/wy
Ze względu na tę zależność od systemu operacyjnego identyczne warunki wyjątku (takie jak błąd nie znaleziono katalogu w naszym przykładzie) mogą skutkować zgłoszeniem dowolnego wyjątku z całej klasy wyjątków wejścia/wyjścia. Oznacza to, że podczas wywoływania interfejsów API do we/wy twój kod powinien być przygotowany na obsługę większości lub wszystkich tych wyjątków, jak pokazano w poniższej tabeli.
| Typ wyjątku | .NET Core/.NET 5+ | Środowisko .NET Framework |
|---|---|---|
| IOException | Tak | Tak |
| FileNotFoundException | Tak | Tak |
| DirectoryNotFoundException | Tak | Tak |
| DriveNotFoundException | Tak | Tak |
| PathTooLongException | Tak | Tak |
| OperationCanceledException | Tak | Tak |
| UnauthorizedAccessException | Tak | Tak |
| ArgumentException | .NET Core 2.0 i starsze wersje | Tak |
| NotSupportedException | Nie. | Tak |
| SecurityException | Nie. | Tylko ograniczone zaufanie |
Obsługa wyjątku IOException
Ponieważ jest to klasa bazowa dla wyjątków w przestrzeni nazw System.IO, IOException jest również wywoływana dla każdego kodu błędu, który nie jest przypisany do wstępnie zdefiniowanego typu wyjątku. Oznacza to, że może zostać zgłoszony przez dowolną operację wejścia/wyjścia.
Ważne
Ponieważ IOException jest bazową klasą innych typów wyjątków w przestrzeni nazw System.IO, należy obsłużyć ją w bloku catch po obsłużeniu innych wyjątków związanych z we/wy.
Ponadto, począwszy od platformy .NET Core 2.1, sprawdzanie poprawności ścieżki (na przykład w celu upewnienia się, że nieprawidłowe znaki nie znajdują się w ścieżce), zostało usunięte, a środowisko uruchomieniowe zgłasza wyjątek zamapowany na kod błędu systemu operacyjnego, a nie z własnego kodu walidacji. Najbardziej prawdopodobnym wyjątkiem, który może być zgłoszony w tym przypadku, jest wyjątek IOException, chociaż można również zgłosić inny typ wyjątku.
Należy pamiętać, że w kodzie obsługi wyjątków IOException powinno być zawsze obsługiwane jako ostatnie. W przeciwnym razie, ponieważ jest to klasa bazowa wszystkich innych wyjątków I/O, bloki catch klas pochodnych nie zostaną uruchomione.
W przypadku elementu IOException można uzyskać dodatkowe informacje o błędzie z właściwości IOException.HResult. Aby przekonwertować wartość HResult na kod błędu Win32, należy usunąć górne 16 bitów wartości 32-bitowej. W poniższej tabeli wymieniono kody błędów, które mogą być opakowane w element IOException.
| HResult | Stały | Opis |
|---|---|---|
| ERROR_SHARING_VIOLATION (naruszenie współdzielenia) | 32 | Brakuje nazwy pliku lub plik bądź katalog jest używany. |
| BŁĄD_PLIK_ISTNIEJE | 80 | Plik już istnieje. |
| BŁĄD_NIEPRAWIDŁOWY_PARAMETR | 87 | Argument dostarczony do metody jest nieprawidłowy. |
| BŁĄD_JUŻ_ISTNIEJE | 183 | Plik lub katalog już istnieje. |
Można je obsłużyć przy użyciu When klauzuli w instrukcji catch, jak pokazano w poniższym przykładzie.
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