Почему в path подставляется file java
Перейти к содержимому

Почему в path подставляется file java

  • автор:

Почему операции над Path реализованы через статические методы?

ИМХО, path.delete() выглядит лучше, чем Files.delete(path) . Но разработчики пакета java.nio.file предпочли реализовать операции с Path через статические методы класса Files . Почему? Т. е. интерфейс Path можно было бы заменить на абстрактный класс с методами delete() , isDirectory() и пр., точно так же получив удобный механизм для реализации платформозависимых сущностей.

Отслеживать
задан 16 мар 2014 в 19:06
Nelson Tatius Nelson Tatius
2,738 3 3 золотых знака 31 31 серебряный знак 45 45 бронзовых знаков

какой смысл в объекте path после вызова у него delete()? путь/линк/файл удален и сам объект представляет собой что? * PHP:unlink * Delphi:RemoveDir * C++:boost::filesystem::remove_all и т.д.

16 мар 2014 в 21:28

@Yura Ivanov, в противовес предложу j.u.File.delete(). Объект продолжает описывать некий путь, только еще не созданный.

17 мар 2014 в 7:21
@Yura Ivanov, в PHP unlink все-таки слишком рано появился, чтобы могла быть альтернатива.
17 мар 2014 в 8:27

@Nofate, все верно, если работаем с файлом, значит можем его создать, изменить, удалить и т.д. а если только удалить надо, зачем объект создавать? к тому же методы эти разные по функционалу. И в качестве ответа на вопрос можно заметить, что есть и тот и другой вариант.

17 мар 2014 в 9:53
@Yura Ivanov, так я и не опровергаю вашу точку зрения. Я больше с целью дополнить пример предложил.
17 мар 2014 в 10:30

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Объект java.nio.file.Path — это сущность пути. Если есть объект Path , то это вовсе не значит, что на диске есть файл или папка. По такому пути файл может существовать, а может и не существовать. Путь — просто строка определённого вида.

С путём можно производить действия: проверить, является ли он абсолютным, обрезать его, проверить, с чего он начинается и так далее. Если бы мы писали path.delete() , то это бы звучало как «удалить путь». Путь — вещь абстрактная, его нельзя удалить. Можно удалить только файл, который находиться по этому пути. И поэтому классе Path вообще содержаться методы для работы лишь с абстрактным путём, а не с реальными файлами.

А вот в утилитном классе java.nio.file.Files содержаться методы для работы с реальными файлами. Для получения размера файла, который находится по этому пути, для удаления файла, который находится по этому пути. В этом классе только статические методы, так как привязывать объект к какому-либо файлу некорректно, см. комментарий @Yura Ivanov . А то будет вот как: вы создаёте объект-файл, вызываете на него метод delete() . И что? Файла нет. Тогда объект превращается уже не в файл, а в путь (вот класс, описывающий путь у нас и есть).

А если вам кажется неудобной запись Files.delete(path) , то вы можете использовать более старый класс для работы с файлами — java.io.File . При его использовании как раз и пишут file.delete() . Но имейте ввиду, что метод delete() , как и многие другие методы класса java.io.File , в случае ошибки возвращает false , а не кидает исключение. Да и методов в классе File меньше, чем в Files и Path , и вообще у класса File недостатков хватает, вот в java7 и создали класс Files и интерфейс Path .

Преобразование java.io.File в java.nio.file.Path в Java 6

Для преобразования объекта File в объект Path в Java вам следует воспользоваться методом toPath(), который был добавлен в Java 7:

Скопировать код

Path path = new File("example.txt").toPath();

Такой подход позволяет использовать все преимущества java.nio.file.Path , базируясь на объекте java.io.File .

Путь на более высоком уровне абстракции: Path

Path — это интерфейс, который впервые появился в Java 7 и представляет собой более продвинутый инструмент по сравнению с File . Path не просто обертывает путь к файлу или папке: он представляет реальные элементы файловой системы, поддерживает работу с атрибутами файлов и предлагает расширенные функции, такие как работа с символическими ссылками и отслеживание изменений в директориях.

Использование новых методов Path

Ниже представлены примеры использования классов Paths и Files , демонстрирующие расширенные возможности по работе с файлами:

Скопировать код

// Вот такое обновление. Действительно удобно, не так ли? Files.copy(oldFile.toPath(), newPath, StandardCopyOption.REPLACE_EXISTING); Files.move(oldFile.toPath(), newPath, StandardCopyOption.ATOMIC_MOVE);

Совет для продвинутых пользователей: для улучшения взаимодействия старайтесь максимально использовать методы Path , особенно при работе со специфическими провайдерами файловых систем.

Обработка ситуаций, связанных со старой версией Java 6

Если вы все еще работаете с Java 6, можно получить Path из File , используя FileSystems.getDefault().getPath() :

Скопировать код

File file = new File("legacy.txt"); Path path = FileSystems.getDefault().getPath(file.getPath());

Это некий подтекст к мысли о том, что стоит перейти на более новую версию Java для упрощения работы с файлами.

Визуализация

Можно визуализировать java.io.File как устаревший, но надежный ключ ��, а java.nio.file.Path — как многофункциональный современный инструмент ��:

Исходный Целевой Инструментарий
File (��) Path (��) Широкий спектр возможностей

Примените следующий подход к преобразованию:

Скопировать код

File oldKey = new File("old_school.txt"); // Добрый старый ключ �� Path newTool = oldKey.toPath(); // Многофункциональный новый инструмент ��

И вот, все готово! Теперь вы во всеоружии, чтобы работать с файлами на новом качественном уровне.

Решение проблем, связанных с преобразованием

Ниже представлены несколько практических рекомендаций, которые могут помочь вам при переходе с File на Path :

Поддержка символических ссылок

В отличие от File , Path изначально поддерживает работу с символическими ссылками:

Как читать из файла java

Для работы с файлами можно использовать методы из библиотеки java.nio.file. Библиотека предоставляет классы Path и Paths для работы с путями файлов, а также класс Files для манипулирования с файловой системой.

Сначала нужно сформировать путь к файлу с помощью класса Paths, например используя метод Paths.get(). Получившийся объект нужно использовать в методах класса Files.

Пример чтения файла:

import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; // Получаем путь к нужному файлу Path writeFilePath = Paths.get("/tmp/file.txt"); // Читаем файл String content = Files.readString(path); // Выводим содержимое System.out.println(content); 

18 ноября 2022

Также надо учитывать, что метод readString() может выбросить обрабатываемую ошибку java.io.IOException .

И при его использовании надо или обрамить вызов try-catch , или указать в головном методе throws IOException .

Path path = Paths.get("input.txt"); String contents = ""; try  contents = Files.readString(path); > catch (IOException ex)  // обработка ошибки чтения > 

Java — путь против файла

В Java Path и File — это классы, отвечающие за файловые операции ввода-вывода. Они выполняют одни и те же функции, но относятся к разным пакетам.

В этом уроке мы обсудим различия между этими двумя классами. Мы начнем с краткого обзора класса. Затем мы поговорим о некоторых устаревших недостатках. Наконец, мы узнаем, как перенести функции между обоими API.

2. Класс java.io.Файл ​

Начиная с самых первых версий, Java предоставляет собственный пакет java.io , который содержит почти все классы, которые могут нам когда-либо понадобиться для выполнения операций ввода и вывода. Класс File является абстрактным представлением путей к файлам и каталогам :

 File file = new File("foreach/tutorial.txt"); 

Экземпляры класса File неизменяемы — после создания абстрактный путь, представленный этим объектом, никогда не изменится.

3. Класс java.nio.file.Path ​

Класс Path является частью обновления NIO2 , которое появилось в Java с версией 7. Он предоставляет совершенно новый API для работы с вводом -выводом . Более того, как и устаревший класс File , Path также создает объект, который можно использовать для поиска файла в файловой системе . ** **

Точно так же он может выполнять все операции , которые можно выполнить с классом File :

 Path path = Paths.get("foreach/tutorial.txt"); 

Вместо использования конструктора, как в случае с File API, мы создаем экземпляр Path , используя статический метод java.nio.file.Paths.get() .

4. Недостатки файлового класса​

После этого краткого обзора двух классов давайте теперь обсудим оба API и ответим на вопрос: если они обеспечивают одинаковую функциональность, почему Oracle решила добавить новый API и какой из них мне следует использовать?

Как мы знаем, пакет java .io поставлялся с первым выпуском Java JDK, что позволяло нам выполнять операции ввода-вывода. С тех пор многие разработчики сообщали о многих недостатках, отсутствующих функциях и проблемах с некоторыми из его возможностей.

4.1. Обработка ошибок​

Самая распространенная проблема — плохая обработка ошибок. Многие методы не сообщают нам никаких подробностей о возникшей проблеме и даже не выдают исключений.

Предположим, у нас есть простая программа, которая удаляет файл:

 File file = new File("foreach/tutorial.txt");   boolean result = file.delete(); 

Этот код компилируется и успешно работает без каких-либо ошибок. Конечно, у нас есть флаг результата , содержащий ложное значение, но мы не знаем причину этого сбоя. Файл может не существовать, или у программы может не быть разрешения на его удаление.

Теперь мы можем переписать ту же функциональность, используя более новый API NIO2:

 Path path = Paths.get("foreach/tutorial.txt");   Files.delete(path); 

Теперь компилятор требует от нас обработки IOException . Более того, у выброшенного исключения есть подробности о его сбое, которые сообщат вам, например, если файл не существует.

4.2. Поддержка метаданных​

Класс File в пакете java.io плохо поддерживает метаданные, что приводит к проблемам на разных платформах с операциями ввода-вывода, требующими метаинформации о файлах.

Метаданные могут также включать разрешения, владельца файла и атрибуты безопасности. Из-за этого класс File вообще не поддерживает символические ссылки , а метод rename() работает неодинаково на разных платформах. «

4.3. Масштабирование и производительность метода​

Также существует проблема с производительностью, поскольку методы класса File не масштабируются. Это приводит к проблемам с некоторыми каталогами с большим количеством файлов. Перечисление содержимого каталога может привести к зависанию, вызывая проблемы с ресурсами памяти . Наконец, это может привести к отказу в обслуживании.

Из-за некоторых из этих недостатков Oracle разработал улучшенный API NIO2. Разработчики должны начинать новые проекты, используя этот новый пакет java.nio вместо устаревших классов, где это возможно.

5. Функциональность отображения​

Чтобы исправить некоторые пробелы в пакете java.io , Oracle подготовила собственную сводку недостатков , помогающую разработчикам мигрировать между API.

Пакет NIO2 « предоставляет все устаревшие функции, включая улучшения для упомянутых недостатков. Из-за большого количества приложений, которые все еще могут использовать этот устаревший API, Oracle в настоящее время не планирует объявлять устаревшим или удалять старый API в будущих выпусках.

В новом API вместо методов экземпляра мы используем статические из класса java.nio.file.Files . Давайте теперь быстро сравним эти API.

5.1. Экземпляры файлов и путей ​

Основное отличие, конечно же, в названии пакета и класса:

 java.io.File file = new java.io.File("foreach/tutorial.txt");   java.nio.file.Path path = java.nio.file.Paths.get("foreach/tutorial.txt"); 

Здесь мы создаем объект File с помощью конструктора, а Path получаем с помощью статического метода. Мы также можем разрешать сложные пути, используя несколько аргументов:

 File file = new File("foreach", "tutorial.txt");   Path path = Paths.get("foreach", "tutorial.txt"); 

И мы можем добиться того же результата, объединив метод resolve() :

 Path path2 = Paths.get("foreach").resolve("tutorial.txt"); 

Более того, мы можем конвертировать объекты между API, используя методы toPath() и toFile() :

 Path pathFromFile = file.toPath();   File fileFromPath = path.toFile(); 

5.2. Управление файлами и каталогами​

Оба API предоставляют методы для управления файлами и каталогами. Мы продемонстрируем это, используя ранее созданные объекты-экземпляры.

Для создания файлов мы можем использовать методы createNewFile( ) и Files.createFile() :

 boolean result = file.createNewFile();   Path newPath = Files.createFile(path); 

Чтобы создать каталог , нам нужно использовать mkdir() или Files.createDirectory() :

 boolean result = file.mkdir();  File newPath = Files.createDirectory(path); 

Существуют дополнительные варианты этих методов для включения всех несуществующих подкаталогов с помощью методов mkdirs() и Files.createDirectories() :

 boolean result = file.mkdirs();   File newPath = Files.createDirectories(path); 

Когда мы хотим переименовать или переместить файл , нам нужно создать другой экземпляр объекта и использовать renameTo() или Files.move() :

 boolean result = file.renameTo(new File("foreach/tutorial2.txt"));   Path newPath = Files.move(path, Paths.get("foreach/tutorial2.txt")); 

Чтобы выполнить операцию удаления , мы используем delete() или Files.delete() :

 boolean result = file.delete();   Files.delete(Paths.get(path)); 

Обратите внимание, что устаревшие методы возвращают флаг с результатом, равным false , в случае каких-либо ошибок. Методы NIO2 возвращают новый экземпляр Path , за исключением операции удаления, которая генерирует исключение IOException при возникновении ошибок.

5.3. Чтение метаданных​

Мы также можем получить некоторую базовую информацию о файлах, такую как разрешения или типы. Как и раньше, нам нужен экземпляр объекта:

 // java.io API   boolean fileExists = file.exists();   boolean fileIsFile = file.isFile();   boolean fileIsDir = file.isDirectory();   boolean fileReadable = file.canRead();   boolean fileWritable = file.canWrite();   boolean fileExecutable = file.canExecute();   boolean fileHidden = file.isHidden();    // java.nio API   boolean pathExists = Files.exists(path);   boolean pathIsFile = Files.isRegularFile(path);   boolean pathIsDir = Files.isDirectory(path);   boolean pathReadable = Files.isReadable(path);   boolean pathWritable = Files.isWritable(path);   boolean pathExecutable = Files.isExecutable(path);   boolean pathHidden = Files.isHidden(path); 

5.4. Методы имени пути​

В заключение давайте быстро рассмотрим методы в классе File для получения пути к файловой системе . Имейте в виду, что, в отличие от предыдущих примеров, большинство из них выполняются непосредственно на экземплярах объектов.

Чтобы получить абсолютные или канонические пути , мы можем использовать:

 // java.io API   String absolutePathStr = file.getAbsolutePath();   String canonicalPathStr = file.getCanonicalPath();    // java.nio API   Path absolutePath = path.toAbsolutePath();   Path canonicalPath = path.toRealPath().normalize(); 

Хотя объект Path неизменяем, он возвращает новый экземпляр. Более того, в NIO2 API есть методы toRealPath() и normalize() , которые мы можем использовать для удаления избыточности.

Преобразование в URI можно выполнить с помощью методов toUri() :

 URI fileUri = file.toURI();   URI pathUri = path.toUri(); 

Кроме того, мы можем перечислить содержимое каталога :

 // java.io API   String[] list = file.list();   File[] files = file.listFiles();    // java.nio API   DirectoryStreamPath> paths = Files.newDirectoryStream(path); 

NIO2 API возвращает собственный объект DirectoryStream , реализующий интерфейс Iterable .

6. Заключение​

Начиная с Java 7 разработчики теперь могут выбирать между двумя API для работы с файлами. В этой статье мы обсудили некоторые различные недостатки и проблемы, связанные с классом java.io.File .

Чтобы исправить их, Oracle решила доставить пакет NIO, который предоставляет ту же функциональность, но со значительными улучшениями .

Затем мы рассмотрели оба API. На примерах мы научились мигрировать между ними. Мы также узнали, что java.io.File теперь считается устаревшим и не рекомендуется для новых проектов . Тем не менее, нет никакого плана, чтобы устареть и удалить его.

Как всегда, все фрагменты кода из этой статьи доступны на GitHub .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *