I/O ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-10-31

Класс File в Java: работа с файлами и каталогами

Строка File file = new File("report.txt"); выполняется без ошибок, но если такого файла ещё не было, он после неё не появится: file.exists() вернёт false, а file.length() — 0, и тоже без всякого исключения. Объект File — это только путь, а не сам файл, и большинство его методов сообщают о проблемах через false, 0 или null.

Класс File (java.io.File) — это представление пути к файлу или каталогу в файловой системе. В отличие от большинства классов ввода-вывода, он не работает с потоками и не читает содержимое файла: с его помощью проверяют, существует ли файл, узнают его размер, дату последнего изменения и права доступа (canRead(), canWrite()), создают, переименовывают и удаляют файлы и каталоги, получают список файлов каталога и перемещаются по иерархии подкаталогов.

Конструкторы класса File

Объект File создаётся одним из четырёх конструкторов: из полного пути, из пути родительского каталога и имени, из объекта File родительского каталога и имени или из URI. Ни один конструктор не обращается к диску и не создаёт файл — он только запоминает путь.

Конструктор Параметры Пример
File(String pathname) Путь к файлу или каталогу (абсолютный или относительный) new File("src/io/file.txt")
File(String parent, String child) Путь к родительскому каталогу и имя файла (или подкаталога) в нём new File("src/io", "file.txt")
File(File parent, String child) Объект File родительского каталога и имя файла в нём new File(dir, "file.txt")
File(URI uri) Объект URI со схемой file:, описывающий файл new File(URI.create("file:///C:/data/file.txt"))

Разделитель каталогов можно писать как / — Java понимает его и в Windows, а при выводе пути заменяет на системный (\). Системный разделитель доступен в константе File.separator, но удобнее всего конструкторы с двумя параметрами: они сами подставляют нужный разделитель.

Откуда считается относительный путь

Относительный путь ("src/io/file.txt") отсчитывается от рабочего каталога JVM — System.getProperty("user.dir"), а не от папки, где лежит класс. В IntelliJ IDEA это по умолчанию корень проекта, а при запуске java -jar — каталог, из которого выполнена команда. Поэтому программа, которая «видит» файл в IDE, может не найти его после сборки.

Методы класса File

Методы класса File делятся на две группы: информационные (имя, путь, размер, существование, тип, права) и операции над файловой системой (создание, переименование, удаление, получение списка файлов). Почти все операции не бросают исключений, а возвращают false — результат нужно проверять.

Информация о файле

Метод Что возвращает Если файла нет
getName() Имя файла или каталога — последний элемент пути Имя из пути
getPath() Путь в том виде, в каком передан в конструктор (с системными разделителями) Путь из конструктора
getAbsolutePath() Абсолютный путь, начиная с корня файловой системы Путь строится всё равно
getParent() Путь родительского каталога в виде строки; getParentFile() — то же в виде File null, если в пути нет родителя (new File("a.txt"))
exists() true, если файл или каталог существует false
isFile() true, если это обычный файл, а не каталог false
isDirectory() true, если это каталог false
isAbsolute() true, если путь абсолютный Зависит только от пути
canRead(), canWrite(), canExecute() Доступен ли файл для чтения, записи, запуска false
length() Размер файла в байтах (long) 0; для каталога значение не определено
lastModified() Время последнего изменения в миллисекундах с 1 января 1970 года (UTC) 0
isHidden() true, если файл скрытый false

Операции над файлами и каталогами

Метод Что делает При неудаче
createNewFile() Создаёт пустой файл, если его ещё нет false, если файл уже есть; IOException, если нет родительского каталога
mkdir() Создаёт один каталог false, если каталог уже есть или нет родительского
mkdirs() Создаёт каталог и все недостающие родительские false, если каталог уже есть или создать не удалось
renameTo(File dest) Переименовывает или перемещает файл; в параметре — объект File с новым путём false (например, файл назначения уже есть или другой диск — зависит от ОС)
delete() Удаляет файл или пустой каталог false, в том числе для непустого каталога
list() Массив имён (String[]) файлов и подкаталогов каталога null, если это не каталог или произошла ошибка
listFiles() Массив объектов File[]; есть перегрузки с FileFilter и FilenameFilter null, как у list()
toPath() Преобразует File в java.nio.file.Path (Java 7+) InvalidPathException при недопустимом пути

Полный список методов — в официальной документации java.io.File (Java 21).

Пример: получение информации о файле

Чтобы получить информацию о файле в Java, достаточно создать объект File и вызвать его информационные методы: getName(), getAbsolutePath(), exists(), length(), lastModified(). Ниже — программа, которая печатает все основные свойства файла.

Пример 1. Получение информации о файле

import java.io.File;
import java.time.Instant;

public class FileExample {
    public static void main(String[] args) {
        File file = new File("src/io/file.txt");

        System.out.println("Имя файла: " + file.getName());
        System.out.println("Путь: " + file.getPath());
        System.out.println("Абсолютный путь: " + file.getAbsolutePath());
        System.out.println("Родительский каталог: " + file.getParent());
        System.out.println(file.exists() ? "Файл/каталог существует." : "Файл/каталог не существует.");
        System.out.println(file.canWrite() ? "Доступен для записи." : "Недоступен для записи.");
        System.out.println(file.canRead() ? "Доступен для чтения." : "Недоступен для чтения.");
        System.out.println(file.isDirectory() ? "Каталог." : "Не каталог.");
        System.out.println(file.isFile() ? "Файл." : "Не файл.");
        System.out.println(file.isAbsolute() ? "Абсолютный путь." : "Не абсолютный путь.");
        System.out.println("Последнее изменение (мс): " + file.lastModified());
        System.out.println("Последнее изменение: " + Instant.ofEpochMilli(file.lastModified()));
        System.out.println("Размер: " + file.length() + " байт.");
    }
}

Вывод (Windows, проект в C:\projects\demo, файл размером 26 байт; время изменения у вас будет своё):

Имя файла: file.txt
Путь: src\io\file.txt
Абсолютный путь: C:\projects\demo\src\io\file.txt
Родительский каталог: src\io
Файл/каталог существует.
Доступен для записи.
Доступен для чтения.
Не каталог.
Файл.
Не абсолютный путь.
Последнее изменение (мс): 1793404800000
Последнее изменение: 2026-10-31T00:00:00Z
Размер: 26 байт.

Если заменить путь на "missing.txt" (такого файла нет), программа отработает без исключений, но значения станут «пустыми»:

Имя файла: missing.txt
Путь: missing.txt
Абсолютный путь: C:\projects\demo\missing.txt
Родительский каталог: null
Файл/каталог не существует.
Недоступен для записи.
Недоступен для чтения.
Не каталог.
Не файл.
Не абсолютный путь.
Последнее изменение (мс): 0
Последнее изменение: 1970-01-01T00:00:00Z
Размер: 0 байт.

Поэтому length() == 0 ещё не значит, что файл пустой: сначала проверяйте exists().

Работа с каталогами: mkdir, mkdirs, list, listFiles

Каталог в Java — тоже объект класса File; для него isDirectory() возвращает true. Каталог создают методами mkdir() (один уровень) и mkdirs() (вместе с недостающими родительскими), а его содержимое получают методами list() (имена) и listFiles() (объекты File).

Разница между mkdir() и mkdirs() видна, когда родительских каталогов ещё нет:

File dir = new File("out/reports/2026");
System.out.println(dir.mkdir());   // false - каталога out/reports нет
System.out.println(dir.mkdirs());  // true  - созданы out, out/reports и out/reports/2026
System.out.println(dir.mkdirs());  // false - каталог уже существует

Метод mkdirs() создаёт как сам каталог, так и все недостающие родительские каталоги. Повторный вызов возвращает false, поэтому «каталог есть» надёжнее проверять через dir.isDirectory(), а не по результату mkdirs().

Пример 2. Получение содержимого каталога

list() возвращает только имена, и для каждого имени пришлось бы заново собирать путь. listFiles() сразу возвращает объекты File, у которых можно вызвать isDirectory():

import java.io.File;
import java.util.Arrays;

public class DirList {
    public static void main(String[] args) {
        File catalog = new File("src");

        File[] files = catalog.listFiles();
        if (files == null) {
            System.out.println(catalog.getName() + " не является каталогом или недоступен");
            return;
        }
        Arrays.sort(files); // порядок listFiles() не гарантирован
        System.out.println("Папка " + catalog.getName());
        for (File file : files) {
            String type = file.isDirectory() ? "каталог" : "файл";
            System.out.println("  " + file.getName() + " - " + type);
        }
    }
}

Вывод (в каталоге src лежат подкаталог io и файл Main.java):

Папка src
  io - каталог
  Main.java - файл

Если каталога src нет, listFiles() вернёт null, и программа напечатает src не является каталогом или недоступен. Без проверки на null цикл for упал бы с NullPointerException.

Чтобы отобрать только нужные файлы, передайте в listFiles() фильтр — например, лямбду FileFilter:

File[] javaFiles = new File("src").listFiles(f -> f.isFile() && f.getName().endsWith(".java"));
// для каталога из примера выше: массив из одного элемента src\Main.java

Создание, переименование и удаление файла

Пустой файл создаёт метод createNewFile(), переименовывает или перемещает — renameTo(File dest), удаляет — delete(). Все три возвращают boolean; проверяемое исключение IOException бросает только createNewFile(), поэтому вызывающий его метод должен обработать исключение или объявить его в throws.

Пример 3. Что выведет этот код?

import java.io.File;
import java.io.IOException;

public class FileOperations {
    public static void main(String[] args) throws IOException {
        File file = new File("temp.txt");
        System.out.println(file.createNewFile());     // 1
        System.out.println(file.createNewFile());     // 2

        File renamed = new File("temp-old.txt");
        System.out.println(file.renameTo(renamed));   // 3
        System.out.println(file.exists());            // 4
        System.out.println(renamed.exists());         // 5
        System.out.println(renamed.delete());         // 6

        File out = new File("out");                   // каталог из примера с mkdirs, внутри out/reports
        System.out.println(out.delete());             // 7
    }
}

Вывод (файлов temp.txt и temp-old.txt до запуска нет):

true
false
true
false
true
true
false

Строка 2 — false: файл уже создан, повторно createNewFile() его не перезаписывает. Строка 4 — false, хотя переименование прошло успешно: объект file по-прежнему указывает на temp.txt, которого больше нет. Строка 7 — false: delete() не удаляет непустой каталог, сначала нужно удалить его содержимое.

Объект File неизменяем

Путь внутри File задаётся один раз в конструкторе и больше не меняется. После renameTo() дальше работайте с объектом, который передали в параметр (renamed), а не с исходным.

Сам File не читает и не записывает содержимое файла — для этого объект File передают в конструктор потока: new FileInputStream(file), new FileReader(file). Чтение и запись разобраны в уроках Типы байтовых потоков и Классы символьных потоков.

File, Path и Files: что выбрать

В Java 7 появился пакет java.nio.file с интерфейсом Path (путь) и утилитным классом Files (операции). Они решают те же задачи, что и java.io.File, но при ошибке бросают исключение с понятной причиной вместо false, умеют копировать файлы и читать их содержимое. В новом коде для работы с файлами обычно выбирают Path и Files; File остаётся в старом коде и в API, которые принимают именно File.

Задача java.io.File java.nio.file.Files
Проверить существование file.exists() Files.exists(path)
Создать файл createNewFile() → false, если есть Files.createFile(path) → FileAlreadyExistsException
Удалить delete() → false без причины Files.delete(path) → NoSuchFileException или DirectoryNotEmptyException
Переименовать, переместить renameTo(dest) → false Files.move(src, dest) → исключение с причиной
Создать каталоги mkdirs() Files.createDirectories(path)
Содержимое каталога listFiles() → File[] или null Files.list(dir) → Stream<Path>
Скопировать файл Метода нет Files.copy(src, dest)
Прочитать текст целиком Метода нет, нужны потоки Files.readString(path) (Java 11)

Переход между API занимает один вызов: file.toPath() и path.toFile(). Поток Stream<Path> из Files.list() держит каталог открытым, его нужно закрывать — почему это важно, см. в уроке Конструкция try-with-resources.

Частые ошибки при работе с File

Большинство ошибок с классом File происходят из-за того, что он молча возвращает false или null вместо исключения, и из-за путей, зависящих от ОС и рабочего каталога. Ниже — что происходит в каждом случае и как исправить.

Ошибка Что происходит Как правильно
for (File f : dir.listFiles()) без проверки NullPointerException, если каталога нет или нет прав Сохранить результат в переменную и проверить на null
Игнорировать результат delete(), mkdir(), renameTo() Операция не выполнилась, а программа идёт дальше, как будто всё в порядке Проверять boolean или использовать Files.delete()/Files.move(), которые бросают исключение
Путь "C:\\data\\file.txt" в коде В Linux и macOS такого пути нет, а обратный слэш — обычный символ имени Брать путь из настроек или собирать через new File(parent, child)
Считать, что length() вернёт размер каталога Для каталога значение не определено (обычно 0 в Windows, 4096 в Linux) Суммировать length() файлов рекурсивно
try (File f = new File("a.txt")) Ошибка компиляции: File не реализует AutoCloseable Закрывать нечего: File не открывает файл. Закрывают потоки, созданные из него

Часто задаваемые вопросы

Устарел ли класс File в Java?

Нет, класс java.io.File не помечен как @Deprecated и поддерживается во всех версиях Java. Но для новых программ рекомендуют Path и Files из java.nio.file: они дают понятные исключения и больше операций. Сравнение по задачам — в разделе File, Path и Files.

Чем getAbsolutePath() отличается от getCanonicalPath()?

getAbsolutePath() просто добавляет к относительному пути рабочий каталог: для new File("src/../pom.xml") получится C:\projects\demo\src\..\pom.xml. getCanonicalPath() обращается к файловой системе, убирает . и .., раскрывает символические ссылки и вернёт C:\projects\demo\pom.xml; он может выбросить IOException. Канонический путь используют, чтобы сравнить, указывают ли два пути на один файл.

Чем createNewFile() отличается от new FileOutputStream(file)?

Оба создают файл, если его нет. Но если файл уже существует, createNewFile() вернёт false и не тронет его, а new FileOutputStream(file) молча обрежет его до 0 байт — содержимое пропадёт. Чтобы дописать в конец, используют new FileOutputStream(file, true).

Как получить расширение файла через File?

Отдельного метода в классе File нет. Расширение берут из имени: String name = file.getName(); int dot = name.lastIndexOf('.'); String ext = dot > 0 ? name.substring(dot + 1) : "";. Условие dot > 0 отсекает скрытые файлы вроде .gitignore, у которых точка стоит первой.

Как удалить каталог вместе с содержимым?

Метод delete() удаляет только пустой каталог, поэтому сначала рекурсивно удаляют вложенные файлы и подкаталоги: пройти по listFiles(), для каждого подкаталога вызвать тот же метод, затем удалить сам каталог. Готового метода «удалить всё» нет ни в File, ни в Files.

Практика по теме

Закрепите урок на задачах — у каждой есть уровень и оценка времени.

Все задачи модуля →

Комментарии

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.