JavaRush /Курсы /C# SELF /Перехват файловых исключений (

Перехват файловых исключений ( try-catch)

C# SELF
38 уровень , 1 лекция
Открыта

1. Введение

Операции с файлами почти всегда связаны с внешними по отношению к программе обстоятельствами: файл может быть удалён, перемещён, заблокирован другой программой, вдруг у пользователя кончились права или свободное место на диске. Всё это может привести к исключениям — специальным ситуациям, когда выполнение программы прерывается и “выбрасывается” объект исключения (Exception). Если не поймать и не обработать такое исключение, ваша программа завершится с ошибкой и покажет пользователю страшный красный текст в консоли (или, ещё хуже — молча упадёт).

В C# для обработки таких ситуаций используется блок try-catch (или, по-простому, “ловушка ошибок”). Он позволяет не только "поймать" ошибку, но и спокойно решить, что делать дальше: показать дружелюбное сообщение, предложить выбрать другой файл, записать ошибку в лог или просто повторить попытку.

В реальных приложениях

Если вы пишете консольный калькулятор, то, наверное, можно обойтись и без ловли ошибок при работе с файлами. А вот если у вас программа для обработки документов на предприятии или игра, сохраняющая процесс — не обрабатывать такие ошибки сродни попытке ходить по канату без страховки: рано или поздно что-нибудь да случится.

2. Вспоминаем работу с исключениями

Базовый синтаксис try-catch

Прежде чем перейти к конкретным ситуациям с файлами, напомним базовый синтаксис конструкции try-catch (которую мы уже встречали в лекциях об исключениях):


try
{
    // Здесь код, который может "выбросить" исключение
}
catch (Exception ex)
{
    // Здесь мы ловим все возможные исключения... Но лучше так не делать!
    Console.WriteLine("Что-то пошло не так: " + ex.Message);
}

Внутри try мы пишем потенциально опасный код, а в catch — что делать, если тут что-то пошло не так.

Шутка программиста: "try-catch — это такой цифровой аналог шапки-невидимки для ошибок. Ошибка есть, но вы её не видите!"

Файловые исключения

Когда вы работаете с файлами через .NET, чаще всего вы встречаете исключения — скажем, при создании потока, чтении или записи. Вот несколько типовых сценариев и связанных с ними исключений:

  • Файл не найден → FileNotFoundException
  • Нет доступа к файлу/директории → UnauthorizedAccessException
  • Проблемы с путём (например, недопустимые символы, слишком длинный путь) → PathTooLongException, ArgumentException
  • Файл уже используется другим процессом → IOException
  • Нет свободного места на диске → IOException

Чаще всего с файловыми операциями связаны именно производные от IOException. Все они унаследованы от базового типа System.Exception.

3. Практика: ловим и обрабатываем ошибки при работе с файлами

Давайте рассмотрим типовые случаи на примерах нашего “развивающегося приложения”: предположим, мы пытаемся считать приветствие из файла, обработать его и вывести пользователю. Мы добавим сюда проверку наличия ошибок с помощью try-catch.

Пример 1: Обработка "файл не найден"


string filePath = "hello.txt";

try
{
    string greeting = File.ReadAllText(filePath);
    Console.WriteLine("Содержимое файла: " + greeting);
}
catch (FileNotFoundException ex)
{
    Console.WriteLine("Файл не найден! Проверьте, что файл " + filePath + " существует.");
    // Можем дополнительно вывести подробности
    Console.WriteLine("Технические детали: " + ex.Message);
}

Если файл "hello.txt" отсутствует, программа не завершится с ошибкой, а выведет дружелюбное сообщение. Вот так просто делаем программу устойчивой к "дуратским" ошибкам пользователя.

Пример 2: Нарушение прав доступа

Возьмём ситуацию посложнее: файл есть, но у нас нет прав на его чтение (например, кто-то нарочно дал права только на запись или файл лежит в защищённой папке).


try
{
    string secret = File.ReadAllText("C:\\Windows\\System32\\config.txt");
}
catch (UnauthorizedAccessException ex)
{
    Console.WriteLine("Нет доступа к файлу! Попробуйте запустить программу от имени администратора.");
    Console.WriteLine("Техническая причина: " + ex.Message);
}

Пример 3: Общий IOException

Некоторые ошибки могут быть связаны с конфликтом блокировок (например, другой процесс удерживает файл открытым), с нехваткой места на диске или проблемами с оборудованием:


try
{
    File.WriteAllText("important.txt", "Важная информация!");
}
catch (IOException ex)
{
    Console.WriteLine("Ошибка при работе с файлом: скорее всего, он используется другой программой или на диске недостаточно места.");
    Console.WriteLine("Техническая причина: " + ex.Message);
}

4. Перехват нескольких исключений: выборочная обработка

Иногда нужно по-разному реагировать на разные типы исключений. В .NET разрешается указывать сразу несколько блоков catch — от более частных к более общим (иначе компилятор устроит вашему коду громкую итальянскую забастовку).


try
{
    string content = File.ReadAllText("file.txt");
    Console.WriteLine(content);
}
catch (FileNotFoundException ex)
{
    Console.WriteLine("Файл не найден.");
}
catch (UnauthorizedAccessException ex)
{
    Console.WriteLine("Нет доступа к файлу!");
}
catch (IOException ex)
{
    Console.WriteLine("Другая ошибка ввода-вывода: " + ex.Message);
}

Важно: если поставить catch (Exception ex) первым, остальные блоки не будут иметь смысла, т.к. базовый тип перехватит всё!

5. Вложенные try-catch и повторные попытки

Иногда вы хотите не только обработать ошибку, но и дать пользователю шанс “исправиться” — например, предложить ввести путь до существующего файла:


string filePath;
string content;
int attempts = 0;
const int maxAttempts = 3;

do
{
    Console.Write("Введите путь к файлу: ");
    filePath = Console.ReadLine();

    try
    {
        content = File.ReadAllText(filePath);
        Console.WriteLine("Содержимое файла:\n" + content);
        break;
    }
    catch (FileNotFoundException)
    {
        Console.WriteLine("Файл не найден! Попробуйте ещё раз.");
    }
    catch (UnauthorizedAccessException)
    {
        Console.WriteLine("Нет доступа к файлу! Попробуйте другой файл.");
    }
    attempts++;
}
while (attempts < maxAttempts);

if (attempts == maxAttempts)
    Console.WriteLine("Слишком много неудачных попыток.");

Этот код — маленький "интерфейс дружбы" для пользователя, который забыл, куда сохранил файл.

6. Типичные ошибки и особенности: от лени к осознанности

Очень частая ошибка новичков (и даже бывалых разработчиков) — ловить вообще все исключения подряд, писать просто catch (Exception) и выводить "Произошла ошибка!", не думая о причинах. Такой подход плох по нескольким причинам. Во-первых, он скрывает реальные недочёты в бизнес-логике приложения. Во-вторых, другие, не связанные с файлами ошибки (например, опечатки в коде или ошибка в математике), могут быть случайно проглочены, и поиск настоящей причины затянется надолго.

Гораздо лучше — явно ловить только те ошибки, которые вы способны обработать осмысленно. Если непонятно, какая ошибка произошла, лучше дать ей "упасть" — то есть не ловить её вообще: пусть приложение упадёт, но вы увидите стек вызовов и поймёте, что нужно починить.

Особенность: Некоторые исключения могут быть с вложенными причинами (InnerException). Их удобно анализировать для более подробной диагностики, особенно когда пишете журналы ошибок (логи).

Ещё один нюанс — если после catch-блока жизнь программы невозможна (например, если не удалось открыть главный файл настроек), можно завершить выполнение через return или даже выбросить исключение снова (throw;), чтобы не плодить "зомби-программ" с половиной функций.

2
Задача
C# SELF, 38 уровень, 1 лекция
Недоступна
Обработка нескольких исключений при записи в файл
Обработка нескольких исключений при записи в файл
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ