Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Además de las excepciones que se pueden producir en cualquier llamada de método (por ejemplo, OutOfMemoryException cuando un sistema está estresado o debido a un NullReferenceException error del programador), los métodos del sistema de archivos de .NET pueden producir las siguientes excepciones:
- System.IO.IOException, la clase base de todos los System.IO tipos de excepción. Se produce por errores cuyos códigos de retorno del sistema operativo no se asignan directamente a cualquier otro tipo de excepción.
- System.IO.FileNotFoundException.
- System.IO.DirectoryNotFoundException.
- DriveNotFoundException.
- System.IO.PathTooLongException.
- System.OperationCanceledException.
- System.UnauthorizedAccessException.
- System.ArgumentException, que se produce para caracteres de ruta no válidos en .NET Framework y en .NET Core 2.0 y versiones anteriores.
- System.NotSupportedException, que se produce para dos puntos no válidos en .NET Framework.
- System.Security.SecurityException, que se produce para las aplicaciones que se ejecutan con confianza limitada y que carecen de los permisos necesarios solo en .NET Framework. (Plena confianza es el valor predeterminado en .NET Framework).
Asignación de códigos de error a excepciones
Dado que el sistema de archivos es un recurso de sistema operativo, los métodos de E/S en .NET Core y .NET Framework encapsulan llamadas al sistema operativo subyacente. Cuando se produce un error de E/S en el código ejecutado por el sistema operativo, el sistema operativo devuelve información de error al método de E/S de .NET. A continuación, el método traduce la información de error, normalmente en forma de código de error, en un tipo de excepción de .NET. En la mayoría de los casos, lo hace traduciendo directamente el código de error en su tipo de excepción correspondiente; no realiza ninguna asignación especial del error en función del contexto de la llamada al método.
Por ejemplo, en el sistema operativo Windows, una llamada de método que devuelve un código de error de ERROR_FILE_NOT_FOUND
(o 0x02) se asigna a un FileNotFoundExceptiony un código de error de ERROR_PATH_NOT_FOUND
(o 0x03) se asigna a .DirectoryNotFoundException
Sin embargo, las condiciones precisas en las que el sistema operativo devuelve códigos de error concretos a menudo no están documentados o están mal documentados. Como resultado, se pueden producir excepciones inesperadas. Por ejemplo, puesto que está trabajando con un directorio en lugar de un archivo, cabría esperar que proporcionar una ruta de acceso de directorio no válida para el constructor DirectoryInfo produzca DirectoryNotFoundException. Sin embargo, también puede producir FileNotFoundException.
Control de excepciones en operaciones de E/S
Debido a esta dependencia del sistema operativo, las condiciones de excepción idénticas (como el directorio no encontrado en nuestro ejemplo) pueden dar lugar a que un método de E/S inicie cualquiera de la clase completa de excepciones de E/S. Esto significa que, al llamar a las API de E/S, el código debe estar preparado para controlar la mayoría o todas estas excepciones, como se muestra en la tabla siguiente:
Tipo de excepción | .NET Core/.NET 5+ | .NET Framework |
---|---|---|
IOException | Sí | Sí |
FileNotFoundException | Sí | Sí |
DirectoryNotFoundException | Sí | Sí |
DriveNotFoundException | Sí | Sí |
PathTooLongException | Sí | Sí |
OperationCanceledException | Sí | Sí |
UnauthorizedAccessException | Sí | Sí |
ArgumentException | .NET Core 2.0 y versiones anteriores | Sí |
NotSupportedException | No | Sí |
SecurityException | No | Solo confianza limitada |
Control de excepciones de E/S
Como clase base para excepciones en el System.IO espacio de nombres, IOException también se lanza para cualquier código de error que no se asigne a un tipo de excepción predefinido. Esto significa que se puede iniciar con cualquier operación de E/S.
Importante
Dado que IOException es la clase base de los otros tipos de excepción en el espacio de nombres System.IO, se debe controlar en un bloque catch
después de haber controlado las otras excepciones relacionadas con E/S.
Además, a partir de .NET Core 2.1, las comprobaciones de validación de la corrección de la ruta de acceso (por ejemplo, para asegurarse de que los caracteres no válidos no están presentes en una ruta de acceso) se han quitado y el tiempo de ejecución inicia una excepción asignada desde un código de error del sistema operativo en lugar de desde su propio código de validación. La excepción más probable que se produzca en este caso es , IOExceptionaunque también se podría producir cualquier otro tipo de excepción.
Tenga en cuenta que, en el código de control de excepciones, siempre debe controlar la última clase IOException. De lo contrario, como se trata de la clase base de todas las excepciones de E/S, los bloques catch de las clases derivadas no se evaluarán.
En el caso de un IOException, puede obtener información de error adicional de la propiedad IOException.HResult . Para convertir el valor HResult en un código de error win32, se quitan los 16 bits superiores del valor de 32 bits. En la tabla siguiente se enumeran los códigos de error que se pueden encapsular en un IOException.
HResult | Constante | Descripción |
---|---|---|
ERROR_COMPARTICIÓN_VIOLACIÓN | 32 | Falta el nombre de archivo, o el archivo o directorio está en uso. |
ERROR_FILE_EXISTS | 80 | El archivo ya existe. |
ERROR_PARÁMETRO_NO_VÁLIDO | 87 | Un argumento proporcionado al método no es válido. |
ERROR_YA_EXISTE | 183 | El archivo o directorio ya existe. |
Puede controlarlos con una cláusula When
en una instrucción catch, como se muestra en el ejemplo siguiente.
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