1. Класс Path

Если вы хотите написать программу, которая делает что-то с файлами на диске, это у вас очень легко получится. В Java очень много классов, которые помогают вам работать как с самими файлами, так и с их содержимым.

В ранних версиях Java для работы с файлами использовались классы типа File и FileInputStream. Но теперь класс File считается устаревшим, и использовать его не рекомендуется. Вы, конечно, можете еще встретить его в коде, параметрах методов или конструкторах классов.

Мы будем начинать изучение работы с файлами сразу с класса Path. Path — это класс, который пришел на смену File. Работа с ним безопаснее и эффективнее.

Класс Path

Технически Path — это не класс, а интерфейс. Так сделано для того, чтобы можно было под каждую операционную (и файловую) систему писать свой класс-наследник Path.

У Windows свои стандарты написания пути файлов, у Linux — свои. А ведь в мире еще много операционных систем, и у каждой — свои стандарты.

Поэтому везде в методах для работы с файлами указан интерфейс Path, а реально работа идет с его классами-наследниками: WindowsPath, UnixPath, ...

Создание объекта Path

Чтобы создать объект Path (на самом деле это будет объект класса-наследника — WindowsPath), нужно воспользоваться командой вида:

Path имя = Path.of(путь);

Где имя — это имя переменной типа Path. путь — это путь к файлу (или директории) вместе с именем файла (или директории). А of — статический метод класса Path.

Метод of() используется для того, чтобы создать объекты типа WindowsPath если программа запускается под Windows, а если программа запускается под Linux — объекты UnixPath. Вы не можете создать объект типа Path с помощью кода вида new Path().

Примеры:

Код Примечание
Path file = Path.of("c:\\projects\\note.txt");
Путь к файлу
Path directory = Path.of("c:\\projects\\");
Путь к директории

Файл (или директория) не обязаны существовать, чтобы мог существовать валидный объект типа Path. Может вы только хотите создать файл... Объект типа Path — это как продвинутая версия типа String — он не привязан к конкретному файлу на диске: он просто хранит некий путь на диске и все.


2. Методы типа Path

У интерфейса Path есть довольно много интересных методов. Самые интересные представлены в таблице ниже.

Метод Описание
Path getParent()
Возвращает родительскую директорию
Path getFileName()
Возвращает имя файла без директории
Path getRoot()
Возвращает корневую директорию из пути
boolean isAbsolute()
Проверяет, что текущий путь — абсолютный
Path toAbsolutePath()
Преобразует путь в абсолютный
Path normalize()
Убирает шаблоны в имени директории.
Path resolve(Path other)
Строит новый абсолютный путь из абсолютного и относительного.
Path relativize(Path other)
Получает относительный путь из двух абсолютных путей.
boolean startsWith(Path other)
Проверяет, что текущий путь начинается с пути
boolean endsWith(Path other)
Проверяет, что текущий путь заканчивается на путь
int getNameCount()
Дробит путь на части с помощью разделителя /.
Возвращает количество частей.
Path getName(int index)
Дробит путь на части с помощью разделителя /.
Возвращает часть по ее номеру.
Path subpath(int beginIndex, int endIndex)
Дробит путь на части с помощью разделителя /.
Возвращает часть пути, заданную интервалом.
File toFile()
Преобразует объект Path в устаревший объект File
URI toUri()
Преобразует объект Path в объект типа URI

Ниже идет краткое описание существующих методов.


3. Разделение пути на части

Метод getParent() возвращает путь, который указывает на родительскую директорию для текущего пути. Независимо от того, был этот путь директорией или файлом:

Код Значение
String str = "c:\\windows\\projects\\note.txt";
Path path = Path.of(str).getParent();
"c:\\windows\\projects\\"
String str = "c:\\windows\\projects\\";
Path path = Path.of(str).getParent();
"c:\\windows\\"
String str = "c:\\";
Path path = Path.of(str).getParent();
null

Метод getFileName() возвращает одно имя файла (или директории) — то, что идет после последнего разделителя:

Код Значение
String str = "c:\\windows\\projects\\note.txt";
Path path = Path.of(str).getFileName();
"note.txt"
String str = "c:\\windows\\projects\\";
Path path = Path.of(str).getFileName();
"projects"
String str = "c:\\";
Path path = Path.of(str).getFileName();
null

Метод getRoot() возвращает путь к корневой директории:

Код Значение
String str = "c:\\windows\\projects\\";
Path path = Path.of(str).getRoot();
"c:\\"


4. Абсолютный и относительный пути

Пути бывают двух типов: абсолютные и относительные. Абсолютный путь начинается с корневой директории. Для Windows это может быть папка c:\, для Linux — директория /

Относительный путь считается относительно какой-то директории. Т.е. это как бы конец пути, но только без начала. Относительный путь можно превратить в абсолютный и наоборот

Метод boolean isAbsolute()

Метод проверяет, является ли текущий путь абсолютным

Код Значение
String str = "c:\\windows\\projects\\note.txt";
boolean abs = Path.of(str).isAbsolute();
true
String str = "src\\com\\javarush\\Main.java";
boolean abs = Path.of(str).isAbsolute();
false

Метод Path toAbsolutePath()

Превращает путь в абсолютный, если нужно — добавляет к нему текущую рабочую директорию:

Код Значение
String str = "c:\\windows\\projects\\note.txt";
Path path = Path.of(str).toAbsolutePath();
"c:\\windows\\projects\\note.txt"
String str = "src\\com\\javarush\\Main.java";
Path path = Path.of(str).toAbsolutePath();
"d:\\work\\src\\com\\javarush\\Main.java"

Метод Path normalize()

В пути вместо имени директории можно писать «..», и это будет означать вернуться на одну директорию назад. Нормализация устраняет эти вещи. Примеры:

Код Значение
String str = "c:\\windows\\..\\projects\\note.txt";
Path path = Path.of(str).normalize();
"c:\\projects\\note.txt"
String str = "src\\com\\javarush\\..\\Main.java";
Path path = Path.of(str).normalize();
"src\\com\\Main.java"

Метод Path relativize(Path other)

Метод relativize() позволяет вычислить «разницу путей»: один путь относительно другого

Код Значение
Path path1 = Path.of("c:\\windows\\projects\\note.txt");
Path path2 = Path.of("c:\\windows\\");
Path result = path2.relativize(path1);
"projects\\note.txt"
Path path1 = Path.of("c:\\windows\\projects\\note.txt");
Path path2 = Path.of("c:\\windows\\");
Path result = path1.relativize(path2);
"..\\.."
Path path1 = Path.of("c:\\aaa\\bbb\\1.txt");
Path path2 = Path.of("d:\\zzz\\y.jpg");
Path result = path1.relativize(path2);
Ошибка IllegalArgumentException:
два пути имеют разный "корень" (разные диски)

Метод Path resolve(Path other)

Метод resolve() выполняет операцию, обратную relativize(): из абсолютного и относительного пути он строит новый абсолютный путь.

Код Значение
Path path1 = Path.of("projects\\note.txt");
Path path2 = Path.of("c:\\windows\\");
Path result = path1.resolve(path2);
"c:\\windows"
Path path1 = Path.of("projects\\note.txt");
Path path2 = Path.of("c:\\windows\\");
Path result = path2.resolve(path1);
"c:\\windows\\projects\\note.txt"

Метод toFile()

Метод возвращает устаревший объект File, который хранит тот же путь к файлу, что и объект Path.

Метод toURI()

Метод преобразует путь к стандарту URI, возвращает объект, который содержит путь к файлу:

Путь к файлу URI к файлу
c:\windows\projects\note.txt
file:///c:/windows/projects/note.txt