Patrzę teraz na fragment kodu Java, który przyjmuje ścieżkę jako ciąg i pobiera jego adres URL za pomocą URL resource = ClassLoader.getSystemClassLoader().getResource(pathAsString);
, a następnie wywołuje String path = resource.getPath()
i ostatecznie wykonuje new File(path);
.
Aha, i są też wezwania do URL url = resource.toURI();
i String file = resource.getFile()
.
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 ...
Różnica między getFile()
i getPath()
jest wyjaśniona tutaj: Jaka jest różnica między url.getFile () a getpath ()? (Co ciekawe, obaj wydają się zwracać Strings, co prawdopodobnie bardzo poprawia mój stan umysłu ...)
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ć?
resource.toString()
dałby ci w jar:file:/C:/path/to/my.jar!/com/example/
końcu (zwróć uwagę na wykrzyknik).
Czy różnica między identyfikatorem URI i adresem URL w Javie polega na tym, że ten pierwszy nie koduje spacji? Por. Pliki, identyfikatory URI i adresy URL są w konflikcie w Javie (ta odpowiedź dość dobrze wyjaśnia ogólną, koncepcyjną różnicę między tymi dwoma terminami: identyfikatory URI i lokalizowanie adresów URL; )
Wreszcie - i najważniejsze - po co mi File
przedmiot; dlaczego Resource ( URL
) nie jest wystarczające? (A czy istnieje obiekt zasobów?)
Przepraszamy, jeśli to pytanie jest trochę niezorganizowane; to po prostu odzwierciedla zamieszanie, które mam ... :)
źródło
Path
FileSystem z NIO :)URL
jest nieprzezroczysty - jak pokazujeszjar:file:
, czyli zasób w.jar
archiwum. Kolosalny że wFile
jest bardzo mało prawdopodobne, aby doprowadzić do niczego użytecznego.Odpowiedzi:
UPDATE 12.04.2017 Sprawdź odpowiedź JvR, ponieważ zawiera bardziej wyczerpujące i dokładne wyjaśnienie!
Zwróć uwagę, że nie uważam się za w 100% kompetentnego do udzielenia odpowiedzi, ale mimo to oto kilka uwag:
File
reprezentuje plik lub katalog dostępny za pośrednictwem systemu plikówURL#getPath
pobiera w części ścieżki adresu URL (protocol://host/path?query
)URL#getFile
zgodnie ze zwrotami JavaDocpath+query
W Javie
URI
to tylko struktura danych służąca do manipulowania samym identyfikatorem ogólnym.URL
z drugiej strony jest tak naprawdę lokalizatorem zasobów i oferuje funkcje umożliwiające rzeczywiste odczytywanie zasobów za pośrednictwem zarejestrowanychURLStreamHandler
adresów.Adresy URL mogą prowadzić do zasobów systemu plików i można utworzyć adres URL dla każdego zasobu systemu plików przy użyciu
file://
protokołu (stąd relacjaFile
<->URL
).Należy również pamiętać, że
URL#getFile
nie ma to związku zjava.io.File
.Wystarczy. Tylko jeśli chcesz przekazać zasób do jakiegoś komponentu, który może pracować tylko z plikami, musisz go pobrać
File
. Jednak nie wszystkie adresy URL zasobów można przekonwertować na adresyFile
.Z punktu widzenia środowiska JRE to tylko termin. Niektóre frameworki zapewniają taką klasę (np . Zasoby Springa ).
źródło
java.nio.file.Path
, co jest w zasadzie zamiennikiem (Java 7+)java.io.File
, ponieważ ten drugi interfejs API był najwyraźniej słabo przemyślany we wczesnych latach Java.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:
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)
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)
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)
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)
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.Mało prawdopodobne. Jeśli plik jar jest na lokalnym systemie plików, nie powinien mieć element zapytania, tak
URL.getPath
iURL.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ć.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.
Nie, nie ma. Jest wiele takich rzeczy, które się tak nazywają, ale nie są one zasobami w sensie
ClassLoader.getResource
.źródło
Odpowiedź Pavela Horala jest miła.
Jak mówi, słowo „plik” ma zupełnie inne (praktycznie niepowiązane) znaczenia w
URL#getFile
vsjava.io.File
- może to część zamieszania.Wystarczy dodać:
Zasobów w Javie jest pojęciem abstrakcyjnym, źródło danych, które mogą być odczytane. Lokalizacja (lub adres) zasobu jest reprezentowana w języku Java przez
URL
obiekt.Zasób może odpowiadać zwykłego pliku w lokalnym systemie plików (szczególnie, gdy jej
URL
zaczynafile://
). Ale zasób jest bardziej ogólny (może to być również jakiś plik przechowywany w słoiku lub jakieś dane do odczytania z sieci, z pamięci lub ...). Jest to również bardziej ograniczone, ponieważFile
(oprócz tego, że jest czymś innym niż zwykły plik: katalog, link) można również utworzyć i zapisać.Pamiętaj, że w Javie
File
obiekt tak naprawdę nie reprezentuje „pliku”, ale lokalizację (pełną nazwę ze ścieżką) pliku. Tak więcFile
obiekt umożliwia zlokalizowanie (i otwarcie) pliku, podobnie jakURL
umożliwia dostęp (i otwieranie) do zasobu. (WResource
Javie nie ma klasy, która reprezentowałaby zasób, ale nie ma też klasy, która reprezentowałaby plik! Raz jeszcze:File
nie jest plikiem, to ścieżka do pliku).źródło
Jak je rozumiem, możesz je podzielić na następujące kategorie:
Oparte na sieci: identyfikatory URI i adresy URL.
I lokalnie: zasoby, ścieżki i pliki
Byłoby łatwiej, gdyby zostały połączone w jedną klasę - są naprawdę zagmatwane: D
Mam nadzieję, że to Ci pomoże :)
(Właśnie przejrzałem dokumentację - zajrzyj na docs.oracle.com)
źródło
Plik jest abstrakcyjną reprezentacją jednostki w lokalnym systemie plików.
Ścieżka to zazwyczaj ciąg znaków wskazujący lokalizację pliku w systemie plików. Zwykle nie zawiera nazwy pliku. Więc c: \ documents \ mystuff \ stuff.txt miałoby ścieżkę o wartości „C: \ documents \ mystuff”. Oczywiście format bezwzględnych nazw plików i ścieżek różni się znacznie w zależności od systemu plików.
URL to zestaw identyfikatorów URI z adresem URL zwykle reprezentującym zasoby dostępne przez http. Nie sądzę, aby istniała jakaś żelazna zasada dotycząca tego, kiedy coś musi być identyfikatorem URI, a nie adresem URL. Identyfikatory URI to ciągi znaków w postaci „protokół: // identyfikator-zasobu”, na przykład bitcoin: // params, http://something.com?param=value . Klasy takie jak URL zazwyczaj zawijają ciąg i dostarczają metody narzędziowe, których String nie miałby powodu podawać.
Nie ma czegoś takiego jak Zasoby, przynajmniej nie w tym sensie, o którym mówisz. To, że metoda nosi nazwę getResource, nie oznacza, że zwraca ona obiekt typu Resource.
Ostatecznie najlepszym sposobem, aby dowiedzieć się, co robią metody klasy, jest utworzenie jej instancji w kodzie, wywołanie metod, a następnie przejście przez tryb debugowania lub wysłanie wyników do System.out.
źródło