Jestem teraz całkowicie zdezorientowany - myślę, że głównie z powodu terminologii. Czy ktoś może przeprowadzić mnie przez różnice lub podać kilka linków do materiałów odpornych na atrapy? Zwłaszcza URI do adresu URL i zasobu do pliku? Wydaje mi się, że powinny być odpowiednio tym samym ...
Terminologia jest zagmatwana i czasami dezorientująca, a w większości zrodziła się z ewolucji języka Java jako interfejsu API i platformy w czasie. Aby zrozumieć, jak te terminy zaczęły oznaczać to, co robią, ważne jest, aby rozpoznać dwie rzeczy, które wpływają na projekt Javy:
- Kompatybilność wsteczna. Stare aplikacje powinny działać na nowszych instalacjach, najlepiej bez modyfikacji. Oznacza to, że stary interfejs API (z jego nazwami i terminologią) musi być obsługiwany przez wszystkie nowsze wersje.
- Wieloplatformowy. Interfejs API powinien zapewniać użyteczną abstrakcję swojej platformy bazowej, niezależnie od tego, czy jest to system operacyjny, czy przeglądarka.
Przedstawię koncepcje i wyjaśnię, jak powstały. Odpowiem potem na inne, konkretne pytania, bo być może będę musiał odnieść się do czegoś w pierwszej części.
Co to jest „zasób”?
Abstrakcyjny, ogólny fragment danych, który można zlokalizować i odczytać. Mówiąc wprost, Java używa tego do odniesienia się do „pliku”, który może nie być plikiem, ale reprezentuje nazwany fragment danych. Nie ma bezpośredniej reprezentacji klasy lub interfejsu w Javie , ale ze względu na swoje właściwości (lokalizowalny, czytelny) jest często reprezentowany przez adres URL.
Ponieważ jednym z wczesnych celów projektowania Javy było uruchomienie w przeglądarce, jako aplikacji piaskownicy (apletów!) Z bardzo ograniczonymi prawami / przywilejami / poświadczeniem bezpieczeństwa, Java czyni wyraźną (teoretyczną) różnicę między plikiem (czymś w lokalnym system plików) i zasób (coś, co musi przeczytać). Dlatego odczytywanie czegoś odnoszącego się do aplikacji (ikon, plików klas itp.) Odbywa się za ClassLoader.getResource
pośrednictwem klasy File, a nie.
Niestety, ponieważ „zasób” jest również użytecznym terminem ogólnym poza tą interpretacją, jest również używany do nazywania bardzo konkretnych rzeczy (np. Klasy ResourceBundle , UIResource , Resource ), które w tym sensie nie są zasobami.
Główne klasy reprezentujące (ścieżka do) zasób to java.nio.file.Path , java.io.File , java.net.URI i java.net.URL .
Plik (java.io, 1.0)
Abstrakcyjna reprezentacja nazw ścieżek do plików i katalogów.
Klasa File reprezentuje zasób, do którego można uzyskać dostęp za pośrednictwem natywnego systemu plików platformy . Zawiera tylko nazwę pliku, więc jest to bardziej ścieżka (patrz dalej), którą platforma hosta interpretuje zgodnie z własnymi ustawieniami, regułami i składnią.
Zwróć uwagę, że plik nie musi wskazywać czegoś lokalnego , tylko coś, co platforma hosta rozumie w kontekście dostępu do pliku, np. Ścieżka UNC w systemie Windows. Jeśli zamontujesz plik ZIP jako system plików w swoim systemie operacyjnym, plik odczyta zawarte w nim wpisy dobrze.
URL (java.net, 1.0)
Adres URL klasy reprezentuje Uniform Resource Locator, czyli wskaźnik do „zasobu” w sieci WWW. Zasobem może być coś tak prostego, jak plik lub katalog, lub może to być odniesienie do bardziej skomplikowanego obiektu, takiego jak zapytanie do bazy danych lub wyszukiwarki.
W połączeniu z pojęciem zasobu adres URL reprezentuje ten zasób w taki sam sposób, jak klasa File reprezentuje plik na platformie hosta: jako strukturalny ciąg, który wskazuje na zasób. URL dodatkowo zawiera schemat, który podpowiada jak dotrzeć do zasobu (gdzie „plik:” jest „zapytaj platformę hosta”), a więc umożliwia wskazywanie zasobów przez HTTP, FTP, wewnątrz JAR i tak dalej.
Niestety, adresy URL mają własną składnię i terminologię, w tym użycie „pliku” i „ścieżki”. W przypadku, gdy adres URL jest adresem URL pliku, URL.getFile zwróci ciąg identyczny z ciągiem ścieżki do pliku, do którego się odwołuje.
Class.getResource
zwraca adres URL: jest bardziej elastyczny niż zwracanie pliku i spełnia wymagania systemu, jak to sobie wyobrażano na początku lat 90-tych.
URI (java.net, 1.4)
Reprezentuje odwołanie do Uniform Resource Identifier (URI).
URI to (niewielka) abstrakcja dotycząca adresu URL. Różnica między URI a URL jest koncepcyjna i głównie akademicka, ale URI jest lepiej zdefiniowany w sensie formalnym i obejmuje szerszy zakres przypadków użycia. Ponieważ adresy URL i URI nie są tym samym, wprowadzono nową klasę, która je reprezentuje, z metodami URI.toURL i URL.toURI do poruszania się między nimi.
W Javie główna różnica między adresem URL a URI polega na tym, że adres URL niesie oczekiwanie, że będzie można go rozwiązać , czyli coś, z czego aplikacja może chcieć uzyskać strumień wejściowy; identyfikator URI jest traktowany bardziej jak abstrakcyjna rzecz, która może wskazywać na coś, co można rozwiązać (i zwykle tak jest), ale to, co oznacza i jak do niego dotrzeć, jest bardziej otwarte na kontekst i interpretację.
Ścieżka (java.nio.file, 1.7)
Obiekt, którego można użyć do zlokalizowania pliku w systemie plików. Zwykle będzie reprezentować ścieżkę pliku zależną od systemu.
Nowy interfejs API plików, oznaczony ikoną w interfejsie Path, zapewnia znacznie większą elastyczność niż może zaoferować klasa File. Interfejs Path jest abstrakcją klasy File i jest częścią interfejsu API New IO File . Tam, gdzie plik koniecznie wskazuje na „plik” w rozumieniu platformy hosta, ścieżka jest bardziej ogólna: reprezentuje plik (zasób) w dowolnym systemie plików.
Ścieżka eliminuje zależność od koncepcji pliku platformy hosta. Może to być wpis w pliku ZIP, plik dostępny przez FTP lub SSH-FS, reprezentacja ścieżki klas aplikacji z wieloma korzeniami lub tak naprawdę wszystko, co można w znaczący sposób przedstawić za pomocą interfejsu FileSystem i jego sterownika, FileSystemProvider. Wprowadza moc „montowania” systemów plików w kontekście aplikacji Java.
Platforma hosta jest reprezentowana przez „domyślny system plików”; kiedy dzwonisz File.toPath
, otrzymasz ścieżkę w domyślnym systemie plików.
Jeśli mam lokalizator, który odwołuje się do klasy lub pakietu w pliku jar, czy te dwa elementy (tj. Ścieżka i ciągi plików) będą się różnić?
Mało prawdopodobne. Jeśli plik jar jest na lokalnym systemie plików, nie powinien mieć element zapytania, tak URL.getPath
i URL.getFile
powinien zwrócić ten sam rezultat. Jednak wybierz ten, którego potrzebujesz: adresy URL plików mogą zazwyczaj nie zawierać składników zapytania, ale i tak mógłbym je dodać.
Wreszcie - i co najważniejsze - dlaczego potrzebuję obiektu File; dlaczego zasób (adres URL) nie jest wystarczający?
Adres URL może nie wystarczyć, ponieważ plik zapewnia dostęp do danych porządkowych, takich jak uprawnienia (do odczytu, zapisu, wykonywania), typ pliku (czy jestem katalogiem?) Oraz możliwość wyszukiwania i manipulowania lokalnym systemem plików. Jeśli potrzebujesz tych funkcji, podaj je w pliku lub ścieżce.
Nie potrzebujesz pliku, jeśli masz dostęp do ścieżki. Jednak niektóre starsze API mogą wymagać pliku.
(A czy istnieje obiekt zasobów?)
Nie, nie ma. Jest wiele takich rzeczy, które się tak nazywają, ale nie są one zasobami w sensie ClassLoader.getResource
.
Path
FileSystem z NIO :)