Зараз я абсолютно розгублений - я думаю, здебільшого через термінологію. Хтось може, будь ласка, провести мене через розбіжності або надати кілька посилань на матеріал, що захищає від манекена? Особливо URI до URL-адреси та ресурсу до файлу? Для мене здається, що вони повинні бути одним і тим же, відповідно ...
Термінологія заплутана і іноді бентежить і в основному породжена еволюцією Java як API та як платформи з часом. Щоб зрозуміти, як ці терміни означали те, що вони роблять, важливо визнати дві речі, які впливають на дизайн Java:
- Зворотна сумісність. Старі програми повинні працювати на нових установках, в ідеалі без змін. Це означає, що старий API (з його назвами та термінологією) потрібно підтримувати у всіх новіших версіях.
- Крос-платформа. API повинен забезпечувати корисну абстракцію базової платформи, будь то операційна система чи браузер.
Я пройдусь по концепціях і тому, як вони виникли. Після цього я відповім на інші Ваші конкретні запитання, оскільки, можливо, мені доведеться звернутися до чогось у першій частині.
Що таке "ресурс"?
Абстрактна загальна інформація, яку можна знайти та прочитати. Помилково кажучи, Java використовує це для позначення "файлу", який може не бути файлом, але представляє іменований фрагмент даних. Він не має прямого представлення класу чи інтерфейсу в Java , але через свої властивості (доступний для читання) він часто представлений URL-адресою.
Оскільки однією з перших цілей Java було розробити всередині браузера, як ізольовану програму (аплети!) З дуже обмеженими правами / привілеями / дозволом безпеки, Java робить чітку (теоретичну) різницю між файлом (щось на локальному файлова система) та ресурс (те, що йому потрібно прочитати). Ось чому читання чогось щодо програми (піктограм, файлів класів тощо) виконується через, ClassLoader.getResource
а не через клас File.
На жаль, оскільки "ресурс" - це також корисний загальний термін поза цим тлумаченням, він також використовується для назви дуже конкретних речей (наприклад, класу ResourceBundle , UIResource , Resource ), які в цьому сенсі не є ресурсом.
Основними класами, що представляють (шлях до) ресурсу, є java.nio.file.Path , java.io.File , java.net.URI та java.net.URL .
Файл (java.io, 1.0)
Абстрактне представлення імен шляхів до файлів та каталогів.
Клас File представляє ресурс, доступний за допомогою власної файлової системи платформи . Він містить лише ім'я файлу, тому насправді це більше шлях (див. Пізніше), який платформа хоста інтерпретує відповідно до власних налаштувань, правил та синтаксису.
Зверніть увагу, що Файлу не потрібно вказувати на щось локальне , а лише на те, що платформа хоста розуміє в контексті доступу до файлів, наприклад, шлях UNC у Windows. Якщо ви змонтуєте файл ZIP як файлову систему у вашій ОС, тоді файл буде добре читати вміщені записи.
URL (java.net, 1.0)
URL-адреса класу представляє уніфікований локатор ресурсів, вказівник на "ресурс" у Всесвітній павутині. Ресурсом може бути щось настільки просте, як файл чи каталог, або може бути посиланням на більш складний об'єкт, наприклад, запит до бази даних або пошукової системи.
У тандемі з концепцією ресурсу URL-адреса представляє цей ресурс так само, як клас File представляє файл на хост-платформі: як структурований рядок, який вказує на ресурс. URL-адреса додатково містить схему, яка вказує на те, як отримати доступ до ресурсу (з "file:" being "ask the host platform"), і тому дозволяє вказувати на ресурси через HTTP, FTP, всередині JAR і багато іншого.
На жаль, URL-адреси мають власний синтаксис та термінологію, включаючи використання "файл" та "шлях". Якщо URL-адреса є URL-адресою файлу, URL.getFile поверне рядок, ідентичний рядку шляху посиланого файлу.
Class.getResource
повертає URL-адресу: вона є гнучкішою, ніж повернення файлу, і вона задовольняє потреби системи, як це уявлялося на початку 1990-х.
URI (java.net, 1.4)
Представляє посилання на уніфікований ідентифікатор ресурсу (URI).
URI - це (незначна) абстракція над URL-адресою. Різниця між URI та URL є концептуальною та переважно академічною, але URI краще визначається у формальному розумінні та охоплює ширший спектр випадків використання. Оскільки URL та URI - це не одне і те ж, для їх представлення було введено новий клас із методами URI.toURL та URL.toURI для переміщення між одними та іншими.
У Java основна відмінність між URL та URI полягає в тому, що URL несе очікування, що його можна вирішити , від чого програма може захотіти InputStream; URI трактується більше як абстрактний річмаджідж, який може вказувати на щось вирішуване (і, як правило, це робить), але те, що він означає і як до нього дійти, є більш відкритим для контексту та інтерпретації.
Шлях (java.nio.file, 1.7)
Об'єкт, за допомогою якого можна знайти файл у файловій системі. Зазвичай він представлятиме системний шлях до файлу.
Новий файловий API, позначений у інтерфейсі Path, забезпечує набагато більшу гнучкість, ніж клас File. Інтерфейс Path є абстракцією класу File і є частиною API нового файлу IO . Там, де Файл обов’язково вказує на „файл”, як його розуміє хост-платформа, Path є більш загальним: він представляє файл (ресурс) у довільній файловій системі.
Шлях забирає опору на концепцію файлу хост-платформи. Це може бути запис у ZIP-файлі, файл, до якого можна отримати доступ за допомогою FTP або SSH-FS, багатокореневе представлення шляху до класу програми або насправді будь-що, що може бути значущим чином представлене через інтерфейс FileSystem та його драйвер FileSystemProvider. Це вводить силу "монтування" файлових систем у контекст програми Java.
Хост-платформа представлена через "файлову систему за замовчуванням"; під час дзвінка File.toPath
ви отримуєте шлях до файлової системи за замовчуванням.
Тепер, якщо у мене є локатор, який посилається на клас або пакет у jar-файлі, чи будуть ці два (тобто шлях до рядків файлів) відрізнятися?
Навряд чи. Якщо файл банку знаходиться на локальній файловій системі, ви не повинні мати компонент запиту, так URL.getPath
і URL.getFile
повинен повертати один і той же результат. Однак виберіть той, який вам потрібен: URL-адреси файлів, як правило, не містять компонентів запиту, але я б міг впевнитись, що все одно додаю один.
Нарешті - і найголовніше - навіщо мені об’єкт File; чому недостатньо ресурсу (URL)?
URL-адреси може бути недостатньо, оскільки файл надає доступ до даних ведення домашнього господарства, таких як дозволи (доступні для читання, запис, виконуваний файл), тип файлу (я каталог?), А також можливість пошуку та керування локальною файловою системою. Якщо це функції, які вам потрібні, тоді надайте їх File або Path.
Вам не потрібен файл, якщо у вас є доступ до шляху. Деякі старі API можуть вимагати файлу.
(А чи є об’єкт Resource?)
Ні, немає. Є багато речей, що називаються подібними, але вони не є ресурсом у тому сенсі ClassLoader.getResource
.
Path
FileSystem від NIO :)