Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Além das exceções que podem ser lançadas em qualquer chamada de método (como um OutOfMemoryException quando um sistema está sobrecarregado ou um NullReferenceException devido a erro do programador), os métodos de manipulação de arquivos do .NET podem lançar as seguintes exceções:
- System.IO.IOException, a classe base de todos os System.IO tipos de exceção. Ela é gerada para erros cujos códigos retornados do sistema operacional não mapeiam diretamente para outro tipo de exceção.
- System.IO.FileNotFoundException.
- System.IO.DirectoryNotFoundException.
- DriveNotFoundException.
- System.IO.PathTooLongException.
- System.OperationCanceledException.
- System.UnauthorizedAccessException.
- System.ArgumentException, gerada para caracteres de caminho inválido no .NET Framework e no .NET Core 2.0 e versões anteriores.
- System.NotSupportedException, gerada para dois-pontos inválidos no .NET Framework.
- System.Security.SecurityException, gerada para aplicativos em execução em confiança limitada que não têm as permissões necessárias somente no .NET Framework. (A confiança total é o padrão no .NET Framework.)
Mapeando códigos de erro para exceções
Como o sistema de arquivos é um recurso do sistema operacional, os métodos de E/S no .NET Core e no .NET Framework encapsulam chamadas para o sistema operacional subjacente. Quando ocorre um erro de E/S no código executado pelo sistema operacional, o sistema operacional retorna informações de erro para o método de E/S do .NET. Em seguida, o método converte as informações de erro, normalmente na forma de um código de erro, em um tipo de exceção .NET. Na maioria dos casos, ele faz isso traduzindo diretamente o código de erro em seu tipo de exceção correspondente; ele não executa nenhum mapeamento especial do erro com base no contexto da chamada de método.
Por exemplo, no sistema operacional Windows, uma chamada de método que retorna um código de erro ( ERROR_FILE_NOT_FOUND
ou 0x02) é mapeada para um FileNotFoundException, e um código de erro ( ERROR_PATH_NOT_FOUND
ou 0x03) é mapeado para um DirectoryNotFoundException.
No entanto, as condições precisas sob as quais o sistema operacional retorna códigos de erro específicos geralmente não são documentadas ou são mal documentadas. Como resultado, exceções inesperadas podem ocorrer. Por exemplo, como você está trabalhando com um diretório em vez de um arquivo, você esperaria que fornecer um caminho de diretório inválido para o DirectoryInfo construtor gerasse um DirectoryNotFoundException. No entanto, isso também pode gerar uma FileNotFoundException.
Tratamento de exceções em operações de E/S
Devido a essa dependência no sistema operacional, condições de exceção idênticas (como o erro de diretório não encontrado em nosso exemplo) podem resultar em um método de E/S gerando qualquer uma das várias exceções de E/S. Isso significa que, ao chamar APIs de E/S, seu código deve estar preparado para lidar com a maioria ou todas essas exceções, conforme mostrado na tabela a seguir:
Tipo de exceção | .NET Core/.NET 5+ | .NET Framework |
---|---|---|
IOException | Sim | Sim |
FileNotFoundException | Sim | Sim |
DirectoryNotFoundException | Sim | Sim |
DriveNotFoundException | Sim | Sim |
PathTooLongException | Sim | Sim |
OperationCanceledException | Sim | Sim |
UnauthorizedAccessException | Sim | Sim |
ArgumentException | .NET Core 2.0 e anterior | Sim |
NotSupportedException | Não | Sim |
SecurityException | Não | Somente confiança limitada |
Tratamento IOException
Como a classe base para exceções no namespace System.IO, a IOException também é gerada para qualquer código de erro que não é mapeado para um tipo de exceção predefinido. Isso significa que ela pode ser gerada por uma operação de E/S.
Importante
Como IOException é a classe base dos outros tipos de exceção no namespace System.IO, você deve lidar com ele em um bloco catch
depois de manipular as outras exceções relacionadas a E/S.
Além disso, a partir do .NET Core 2.1, as verificações de validação para a correção do caminho (por exemplo, para garantir que caracteres inválidos não estejam presentes em um caminho) foram removidas, e o tempo de execução gera uma exceção mapeada de um código de erro do sistema operacional, em vez de seu próprio código de validação. A exceção mais provável a ser gerada nesse caso é uma IOException, embora qualquer outro tipo de exceção também possa ser gerado.
Observe que, no seu código de tratamento de exceções, você deve sempre tratar a IOException por último. Caso contrário, como ela é a classe base de todas as outras exceções de E/S, os blocos catch de classes derivadas não serão avaliados.
No caso de um IOException, você pode obter informações de erro adicionais da propriedade IOException.HResult . Para converter o valor HResult em um código de erro Win32, remova os 16 bits superiores do valor de 32 bits. A tabela a seguir lista os códigos de erro que podem ser encapsulados em um IOException.
HResult | Constante | Descrição |
---|---|---|
ERROR_SHARING_VIOLATION (Violação de compartilhamento) | 32 | O nome do arquivo está ausente ou o arquivo ou diretório está em uso. |
ERROR_FILE_EXISTS | 80 | O arquivo já existe. |
ERRO_PARÂMETRO_INVÁLIDO | 87 | Um argumento fornecido ao método é inválido. |
ERRO_JÁ_EXISTE | 183 | O arquivo ou diretório já existe. |
Você pode lidar com isso usando uma cláusula When
em uma instrução catch, como demonstrado no exemplo a seguir.
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