Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Förutom de undantag som kan utlösas i valfritt metodanrop (till exempel OutOfMemoryException när ett system är stressat eller på grund av programmerarfel NullReferenceException ) kan .NET-filsystemmetoder utlösa följande undantag:
- System.IO.IOException, basklassen för alla System.IO undantagstyper. Den kastas för fel vars returkoder från operativsystemet inte mappas direkt till någon annan undantagskategori.
- System.IO.FileNotFoundException.
- System.IO.DirectoryNotFoundException.
- DriveNotFoundException.
- System.IO.PathTooLongException.
- System.OperationCanceledException.
- System.UnauthorizedAccessException.
- System.ArgumentException, som kastas för ogiltiga sökvägstecken i .NET Framework och i .NET Core 2.0 och tidigare versionerna.
- System.NotSupportedException, som kastas för ogiltiga kolon i .NET Framework.
- System.Security.SecurityException, som genereras för program som körs i begränsat förtroende och som endast saknar nödvändiga behörigheter för .NET Framework. (Fullständigt förtroende är standardvärdet för .NET Framework.)
Mappa felkoder till undantag
Eftersom filsystemet är en resurs för operativsystemet, innesluter I/O-metoder i både .NET Core och .NET Framework anrop från det underliggande operativsystemet. När ett I/O-fel inträffar i kod som körs av operativsystemet returnerar operativsystemet felinformation till .NET I/O-metoden. Metoden översätter sedan felinformationen, vanligtvis i form av en felkod, till en .NET-undantagstyp. I de flesta fall gör den detta genom att direkt översätta felkoden till motsvarande undantagstyp. den utför inte någon särskild mappning av felet baserat på kontexten för metodanropet.
I Windows-operativsystemet mappas till exempel ett metodanrop som returnerar en felkod ERROR_FILE_NOT_FOUND för (eller 0x02) till en FileNotFoundException, och en felkod ERROR_PATH_NOT_FOUND för (eller 0x03) mappas till en DirectoryNotFoundException.
De exakta villkor under vilka operativsystemet returnerar specifika felkoder är dock ofta odokumenterade eller dåligt dokumenterade. Därför kan oväntade undantag inträffa. Eftersom du till exempel arbetar med en katalog i stället för en fil förväntar du dig att en ogiltig katalogsökväg till DirectoryInfo konstruktorn genererar en DirectoryNotFoundException. Men det kan också kasta en FileNotFoundException.
Undantagshantering i I/O-åtgärder
På grund av detta beroende av operativsystemet kan identiska undantagsvillkor (till exempel att katalogen inte hittades i vårt exempel) leda till att en I/O-metod genererar någon av hela klassen med I/O-undantag. Det innebär att när du anropar I/O-API:er bör koden vara beredd att hantera de flesta eller alla av dessa undantag, som du ser i följande tabell:
| Undantagstyp | .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 och tidigare | Ja |
| NotSupportedException | Nej | Ja |
| SecurityException | Nej | Endast begränsat förtroende |
Hantering av IOException
Som basklass för undantag i System.IO namnområdet IOException genereras även för all felkod som inte mappas till en fördefinierad undantagstyp. Det innebär att den kan kastas av en I/O-åtgärd.
Viktigt!
Eftersom IOException är basklassen för de andra undantagstyperna System.IO i namnområdet bör du hantera i ett catch block när du har hanterat de andra I/O-relaterade undantagen.
Dessutom, från och med .NET Core 2.1, har valideringskontroller för sökvägskorrekthet (t.ex. för att säkerställa att ogiltiga tecken inte förekommer i en sökväg) tagits bort, och körmiljön kastar ett undantag som mappas från en operativsystemfelkod istället för från sin egen valideringskod. Det mest sannolika undantaget som utlöses i det här fallet är en IOException, även om alla andra undantagstyper också kan genereras.
Observera att i koden för undantagshantering bör du alltid hantera den IOException sista. Annars, eftersom det är basklassen för alla andra I/O-undantag, utvärderas inte fångstblocken för härledda klasser.
När det gäller en IOException, kan du få ytterligare felinformation från egenskapen IOException.HResult. Om du vill konvertera HResult-värdet till en Win32-felkod tar du bort de övre 16 bitarna av 32-bitarsvärdet. I följande tabell visas felkoder som kan vara omslutna i en IOException.
| HResult | Konstant | Beskrivning |
|---|---|---|
| FEL_Delningsöverlappning | 32 | Filnamnet saknas eller så används filen eller katalogen. |
| ERROR_FILE_EXISTS | 80 | Filen finns redan. |
| ERROR_INVALID_PARAMETER | 87 | Ett argument som anges i metoden är ogiltigt. |
| ERROR_ALREADY_EXISTS | 183 | Filen eller katalogen finns redan. |
Du kan hantera dessa med hjälp av en When sats i en catch-instruktion, vilket visas i följande exempel.
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