← Назад к вопросам

Какие знаешь исключения при работе с файлами?

1.7 Middle🔥 191 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Исключения при работе с файлами в Java

Работа с файлами и I/O операции - это частый источник ошибок. Java предоставляет иерархию исключений для обработки различных проблем при работе с файлами.

1. Иерархия исключений I/O

public class FileExceptionsHierarchy {
    /*
    Exception
    └── IOException
        ├── FileNotFoundException
        ├── EOFException
        ├── SocketException
        ├── SocketTimeoutException
        └── ... другие
    
    Также:
    - FileAlreadyExistsException (Java 7+)
    - NoSuchFileException (Java 7+)
    - AccessDeniedException (Java 7+)
    - DirectoryNotEmptyException (Java 7+)
    */
}

2. IOException - базовое исключение I/O

Основанное исключение для всех I/O операций:

import java.io.*;

public class IOExceptionExample {
    public static void readFile(String filename) {
        try {
            FileReader reader = new FileReader(filename);
            int data = reader.read();
            reader.close();
        } catch (IOException e) {
            // IOException - базовое исключение для всех I/O ошибок
            System.out.println("I/O error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

3. FileNotFoundException - файл не найден

Выбрасывается когда файл не существует при чтении:

import java.io.*;

public class FileNotFoundExceptionExample {
    public static void readFile(String filename) throws FileNotFoundException {
        // Выбросит FileNotFoundException если файл не существует
        FileInputStream fis = new FileInputStream(filename);
    }
    
    public static void main(String[] args) {
        try {
            readFile("nonexistent.txt");
        } catch (FileNotFoundException e) {
            // FileNotFoundException наследует IOException
            System.out.println("File not found: " + e.getMessage());
            
            // Проверить сам файл
            File file = new File("nonexistent.txt");
            if (!file.exists()) {
                System.out.println("File does not exist");
            }
        }
    }
}

4. NoSuchFileException - файл не найден (NIO)

Лучший способ работы с файлами в современной Java:

import java.nio.file.*;

public class NoSuchFileExceptionExample {
    public static void readFileNIO(String filename) {
        try {
            byte[] content = Files.readAllBytes(Paths.get(filename));
            System.out.println(new String(content));
        } catch (NoSuchFileException e) {
            // Выбрасывается Files API если файл не существует
            System.out.println("File not found: " + e.getFile());
        } catch (IOException e) {
            System.out.println("I/O error: " + e.getMessage());
        }
    }
    
    // Проверить существование
    public static void main(String[] args) {
        Path path = Paths.get("file.txt");
        if (Files.exists(path)) {
            try {
                readFileNIO("file.txt");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

5. AccessDeniedException - недостаточно прав доступа

Выбрасывается когда нет прав на доступ к файлу:

import java.nio.file.*;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Set;

public class AccessDeniedExceptionExample {
    public static void readRestrictedFile(String filename) {
        try {
            byte[] content = Files.readAllBytes(Paths.get(filename));
        } catch (AccessDeniedException e) {
            // Нет прав на чтение
            System.out.println("Access denied: " + e.getFile());
            System.out.println("Message: " + e.getReason());
            
            // Попробовать изменить права (если есть права администратора)
            try {
                Path path = Paths.get(filename);
                Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-r--r--");
                Files.setPosixFilePermissions(path, perms);
            } catch (Exception ex) {
                System.out.println("Cannot change permissions: " + ex.getMessage());
            }
        } catch (IOException e) {
            System.out.println("I/O error: " + e.getMessage());
        }
    }
}

6. FileAlreadyExistsException - файл уже существует

Выбрасывается при попытке создать файл если он уже есть:

import java.nio.file.*;

public class FileAlreadyExistsExceptionExample {
    public static void createNewFile(String filename) {
        try {
            // Создать новый файл, выбросить исключение если уже существует
            Path path = Paths.get(filename);
            Files.createFile(path);
            System.out.println("File created: " + filename);
        } catch (FileAlreadyExistsException e) {
            // Файл уже существует
            System.out.println("File already exists: " + e.getFile());
            
            // Варианты действия:
            // 1. Перезаписать
            // 2. Добавить в конец
            // 3. Создать с другим именем
        } catch (IOException e) {
            System.out.println("I/O error: " + e.getMessage());
        }
    }
    
    // Использование опций
    public static void createWithOptions(String filename) {
        try {
            Path path = Paths.get(filename);
            // Не выбросить исключение если существует
            Files.write(path, "content".getBytes(), 
                StandardOpenOption.CREATE,
                StandardOpenOption.TRUNCATE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

7. DirectoryNotEmptyException - директория не пустая

Выбрасывается при попытке удалить непустую директорию:

import java.nio.file.*;

public class DirectoryNotEmptyExceptionExample {
    public static void deleteDirectory(String dirname) {
        try {
            Path path = Paths.get(dirname);
            Files.delete(path);  // выбросит исключение если не пустая
            System.out.println("Directory deleted");
        } catch (DirectoryNotEmptyException e) {
            // Директория содержит файлы
            System.out.println("Directory not empty: " + e.getFile());
            
            // Рекурсивное удаление
            deleteRecursively(dirname);
        } catch (IOException e) {
            System.out.println("I/O error: " + e.getMessage());
        }
    }
    
    private static void deleteRecursively(String dirname) {
        try {
            Path path = Paths.get(dirname);
            Files.walk(path, FileVisitOption.FOLLOW_LINKS)
                .sorted((p1, p2) -> p2.compareTo(p1))  // обратный порядок
                .forEach(p -> {
                    try {
                        Files.delete(p);
                    } catch (IOException e) {
                        System.err.println("Cannot delete: " + p);
                    }
                });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

8. EOFException - конец файла неожиданно

Выбрасывается при попытке чтения за пределы файла:

import java.io.*;

public class EOFExceptionExample {
    public static void readBinaryFile(String filename) {
        try (DataInputStream dis = new DataInputStream(
                new FileInputStream(filename))) {
            
            // Читаем 4-байтное целое число
            int value = dis.readInt();
            System.out.println("Read: " + value);
        } catch (EOFException e) {
            // Файл не содержит достаточно байтов
            System.out.println("Unexpected end of file");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // Безопасное чтение
    public static void safeRead(String filename) {
        try (DataInputStream dis = new DataInputStream(
                new FileInputStream(filename))) {
            
            while (true) {
                try {
                    int value = dis.readInt();
                    System.out.println("Read: " + value);
                } catch (EOFException e) {
                    System.out.println("End of file reached");
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

9. UncheckedIOException - обёртка для IOException

Java 8+ для работы с потоками и функциональным кодом:

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class UncheckedIOExceptionExample {
    public static void main(String[] args) {
        try {
            // IOException обёртывается в UncheckedIOException
            Stream<String> lines = Files.lines(Paths.get("file.txt"));
            lines.forEach(System.out::println);
        } catch (UncheckedIOException e) {
            // Причина - IOException
            IOException cause = e.getCause();
            System.out.println("I/O error: " + cause.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

10. Best Practices - правильная обработка

import java.nio.file.*;
import java.io.*;

public class FileHandlingBestPractices {
    // ХОРОШО: try-with-resources
    public static String readFileGood(String filename) throws IOException {
        StringBuilder content = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new FileReader(filename))) {
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append("\n");
            }
        }
        return content.toString();
    }
    
    // ЛУЧШЕ: NIO Files API
    public static String readFileBetter(String filename) throws IOException {
        return new String(Files.readAllBytes(Paths.get(filename)));
    }
    
    // ЛУЧШЕ: для больших файлов
    public static void processLargeFile(String filename) throws IOException {
        try (Stream<String> lines = Files.lines(Paths.get(filename))) {
            lines.filter(line -> !line.isEmpty())
                .map(String::trim)
                .forEach(System.out::println);
        }
    }
    
    // Полная обработка ошибок
    public static void robustFileRead(String filename) {
        Path path = Paths.get(filename);
        
        // 1. Проверить существование
        if (!Files.exists(path)) {
            System.out.println("File does not exist");
            return;
        }
        
        // 2. Проверить читаемость
        if (!Files.isReadable(path)) {
            System.out.println("File is not readable");
            return;
        }
        
        // 3. Читать с полной обработкой ошибок
        try {
            byte[] content = Files.readAllBytes(path);
            System.out.println("File size: " + content.length);
        } catch (NoSuchFileException e) {
            System.out.println("File not found: " + e.getFile());
        } catch (AccessDeniedException e) {
            System.out.println("Access denied: " + e.getFile());
        } catch (IOException e) {
            System.out.println("I/O error: " + e.getMessage());
        }
    }
}

Итоговая таблица

Исключение              | Когда выбрасывается
---
FileNotFoundException   | Файл не найден (старый API)
NoSuchFileException     | Файл не найден (NIO)
AccessDeniedException   | Нет прав доступа
FileAlreadyExistsException | Файл уже существует
DirectoryNotEmptyException | Директория не пустая
EOFException            | Конец файла неожиданно
IOException             | Базовое I/O исключение
UncheckedIOException    | Обёртка IOException в потоках

Рекомендации

  1. Используй NIO (java.nio.file) вместо старого java.io
  2. Проверяй существование файла перед операциями
  3. Обрабатывай конкретные исключения, не просто IOException
  4. Используй try-with-resources для автоматического закрытия
  5. Логируй ошибки для отладки
  6. Не игнорируй исключения - обрабатывай их правильно