I/O-hibák kezelése a .NET-ben
A metódushívásokban (például OutOfMemoryException a rendszer stresszes állapotában vagy NullReferenceException programozói hiba miatt) megjelenő kivételeken kívül a .NET fájlrendszer metódusai a következő kivételeket is alkalmazhatják:
- System.IO.IOException, az összes System.IO kivételtípus alaposztálya. Olyan hibák esetén jelenik meg, amelyek visszatérési kódjai az operációs rendszerből nem képeznek le közvetlenül más kivételtípusra.
- System.IO.FileNotFoundException.
- System.IO.DirectoryNotFoundException.
- DriveNotFoundException.
- System.IO.PathTooLongException.
- System.OperationCanceledException.
- System.UnauthorizedAccessException.
- System.ArgumentException, amely érvénytelen elérésiút-karaktereket tartalmaz a .NET-keretrendszer, valamint a .NET Core 2.0-s és korábbi verzióiban.
- System.NotSupportedException, amely .NET-keretrendszer érvénytelen kettőspontra van vetve.
- System.Security.SecurityException, amely a korlátozott megbízhatósággal futó alkalmazásokhoz kerül, amelyek csak .NET-keretrendszer nem rendelkeznek a szükséges engedélyekkel. (A teljes megbízhatóság az alapértelmezett .NET-keretrendszer.)
Hibakódok hozzárendelése kivételekhez
Mivel a fájlrendszer operációsrendszer-erőforrás, az I/O-metódusok a .NET Core-ban és .NET-keretrendszer a mögöttes operációs rendszerre irányuló sortörési hívásokat is. Ha az operációs rendszer által végrehajtott kódban I/O-hiba történik, az operációs rendszer hibainformációkat ad vissza a .NET I/O metódusnak. A metódus ezután a hibainformációkat általában hibakód formájában .NET-kivételtípusra fordítja le. A legtöbb esetben ezt úgy teszi meg, hogy közvetlenül lefordítja a hibakódot a megfelelő kivételtípusra; nem végez a hiba speciális leképezését a metódushívás kontextusa alapján.
A Windows operációs rendszeren például egy metódushívás, amely egy (vagy 0x02) leképezési hibakódot ERROR_FILE_NOT_FOUND
ad vissza egy FileNotFoundException, és egy (vagy 0x03) leképezés hibakódját ERROR_PATH_NOT_FOUND
egy DirectoryNotFoundException.
Az operációs rendszer által adott hibakódokat visszaadó pontos feltételek azonban gyakran nem dokumentálva vagy rosszul dokumentálva lesznek. Emiatt váratlan kivételek léphetnek fel. Mivel például nem fájllal, hanem könyvtárral dolgozik, azt várhatja, hogy a konstruktornak érvénytelen könyvtárelérési DirectoryInfo út megadása egy DirectoryNotFoundException. Azonban, akkor is dobja a FileNotFoundException.
Kivételkezelés az I/O-műveletekben
Az operációs rendszerre való támaszkodás miatt az azonos kivételfeltételek (például a példában nem található könyvtár) egy I/O-metódust eredményezhetnek, amely az I/O-kivételek teljes osztályának bármelyikét eldobja. Ez azt jelenti, hogy az I/O API-k meghívásakor a kódnak készen kell állnia a kivételek többségének vagy mindegyikének kezelésére, ahogyan az az alábbi táblázatban látható:
Kivételtípus | .NET Core/.NET 5+ | .NET-keretrendszer |
---|---|---|
IOException | Igen | Igen |
FileNotFoundException | Igen | Igen |
DirectoryNotFoundException | Igen | Igen |
DriveNotFoundException | Igen | Igen |
PathTooLongException | Igen | Igen |
OperationCanceledException | Igen | Igen |
UnauthorizedAccessException | Igen | Igen |
ArgumentException | .NET Core 2.0 és korábbi verziók | Igen |
NotSupportedException | Nem | Igen |
SecurityException | Nem | Csak korlátozott megbízhatóság |
IOException kezelése
A névtérben lévő kivételek alaposztályaként minden System.IO olyan hibakód is megjelenik, IOException amely nem képez le előre definiált kivételtípust. Ez azt jelenti, hogy bármilyen I/O-művelettel eldobható.
Fontos
Mivel IOException a névtér többi kivételtípusának System.IO alaposztálya, a többi I/O-kivétel kezelése után egy catch
blokkban kell kezelnie.
A .NET Core 2.1-től kezdődően az ellenőrzés ellenőrzi az elérési út helyességét (például annak biztosítása érdekében, hogy érvénytelen karakterek ne szerepeljenek az elérési utakon), és a futtatókörnyezet kivételt képez ki egy operációs rendszer hibakódjából, nem pedig saját érvényesítési kódjából. Ebben az esetben a legvalószínűbb kivétel egy IOException, bár bármilyen más kivételtípust is ki lehet dobni.
Vegye figyelembe, hogy a kivételkezelési kódban mindig az utolsót IOException kell kezelnie. Ellenkező esetben, mivel ez az összes többi I/O-kivétel alaposztálya, a származtatott osztályok fogási blokkjainak kiértékelése nem történik meg.
Egy esetben IOExceptiontovábbi hibainformációkat kaphat az IOException.HResult tulajdonságból. Ha a HResult értéket Win32 hibakódmá szeretné alakítani, a 32 bites érték felső 16 bitét sztriptízelheti. Az alábbi táblázat azokat a hibakódokat sorolja fel, amelyek becsomagolhatók egy IOException.
HResult | Állandó | Leírás |
---|---|---|
ERROR_SHARING_VIOLATION | 32 | Hiányzik a fájlnév, vagy a fájl vagy könyvtár használatban van. |
ERROR_FILE_EXISTS | 80 | A fájl már létezik. |
ERROR_INVALID_PARAMETER | 87 | A metódushoz megadott argumentum érvénytelen. |
ERROR_ALREADY_EXISTS | 183 | A fájl vagy könyvtár már létezik. |
Ezeket egy When
fogási utasítás záradékával kezelheti, ahogyan az alábbi példa is mutatja.
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
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: