Mój kod działa w pliku JAR, powiedzmy foo.jar , i muszę wiedzieć w kodzie, w którym folderze jest uruchomiony plik foo.jar .
Tak więc, jeśli jest uruchomiony plik foo.jarC:\FOO\
, chcę uzyskać tę ścieżkę bez względu na mój bieżący katalog roboczy.
java
path
jar
executable-jar
Thiago Chaves
źródło
źródło
Odpowiedzi:
Zamień „MyClass” na nazwę swojej klasy.
Oczywiście zrobi to dziwne rzeczy, jeśli klasa została załadowana z lokalizacji innej niż plik.
źródło
toURI()
krok jest niezbędny, aby uniknąć problemów ze znakami specjalnymi, w tym spacjami i plusami. Prawidłowy jednowierszowy to:return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI());
UżywanieURLDecoder
nie działa w przypadku wielu znaków specjalnych. Zobacz moją odpowiedź poniżej, aby uzyskać więcej informacji.getProtectionDomain
jest zerowy, jeśli pobierasz klasę z trasy:val strace = Thread.currentThread().getStackTrace; val path = strace(1).getClass.getProtectionDomain
Najlepsze rozwiązanie dla mnie:
To powinno rozwiązać problem ze spacjami i znakami specjalnymi.
źródło
URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
) w systemie Linux. Nie próbowałem jednak w systemie Windows.URLDecoder
do dekodowania znaków specjalnych. W szczególności takie znaki+
zostaną błędnie zdekodowane na spacje. Zobacz moją odpowiedź, aby poznać szczegóły.Aby uzyskać
File
dla danegoClass
, istnieją dwa kroki:Class
do AURL
URL
do AFile
Ważne jest, aby zrozumieć oba kroki i nie łączyć ich.
Gdy już to
File
zrobisz, możesz zadzwonićgetParentFile
aby uzyskać folder zawierający, jeśli tego potrzebujesz.Krok 1:
Class
doURL
Jak omówiono w innych odpowiedziach, istnieją dwa główne sposoby znalezienia związku
URL
zClass
.URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();
URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");
Oba mają zalety i wady.
getProtectionDomain
Podejście daje położenie podstawy klasy (na przykład zawierający plik JAR). Możliwe jest jednak, że zasady bezpieczeństwa środowiska wykonawczego Java zostaną wyrzuconeSecurityException
podczas wywoływaniagetProtectionDomain()
, więc jeśli aplikacja musi działać w różnych środowiskach, najlepiej przetestować je we wszystkich.getResource
Podejście daje pełną ścieżkę URL zasobu klasy, z której trzeba będzie wykonać dodatkowe łańcuchach. Może to byćfile:
ścieżka, ale może to byćjar:file:
lub nawet coś paskudniejszegobundleresource://346.fwk2106232034:4/foo/Bar.class
podczas wykonywania w środowisku OSGi. I odwrotnie,getProtectionDomain
podejście poprawnie daje afile:
adres URL nawet z poziomu OSGi.Zauważ, że jedno
getResource("")
i drugiegetResource(".")
nie powiodło się w moich testach, gdy klasa rezydowała w pliku JAR; oba wywołania zwróciły wartość null. Polecam więc wywołanie nr 2 pokazane powyżej, ponieważ wydaje się bezpieczniejsze.Krok 2:
URL
doFile
Tak czy inaczej, kiedy już masz
URL
, następnym krokiem jest konwersja naFile
. To jest własne wyzwanie; zobacz post na blogu Kohsuke Kawaguchi, aby uzyskać szczegółowe informacje, ale w skrócie możesz użyć,new File(url.toURI())
o ile adres URL jest całkowicie dobrze sformułowany.Na koniec odradzałbym używanie
URLDecoder
. Niektórzy bohaterowie zawartości,:
a/
w szczególności nie może zawierać znaków URL-zakodowane. Z URLDecoder Javadoc:W praktyce na
URLDecoder
ogół nie rzuca sięIllegalArgumentException
tak, jak grozi powyżej. A jeśli ścieżka do pliku ma spacje zakodowane jako%20
, to podejście może wydawać się działać. Jeśli jednak ścieżka do pliku zawiera inne znaki niealfameryczne, takie jak+
problemy zURLDecoder
manipulowaniem ścieżką.Działający kod
Aby wykonać te kroki, możesz mieć metody takie jak następujące:
Te metody można znaleźć w bibliotece SciJava Common :
źródło
Możesz także użyć:
źródło
Użyj ClassLoader.getResource (), aby znaleźć adres URL bieżącej klasy.
Na przykład:
(Ten przykład pochodzi z podobnego pytania ).
Aby znaleźć katalog, musisz ręcznie rozdzielić adres URL. Zobacz samouczek JarClassLoader dotyczący formatu adresu URL jar.
źródło
NPE
ponieważ nie odpowiedziałeś na zadane pytanie (zapytano o ścieżkę do katalogu JAR i odpowiedziałeś na zupełnie inne pytanie: ścieżka do klasy). 2. Jak zauważyli inni i mam ten sam problem, nie działa dla apletów. 3. Zwrot ścieżka nie jest kanoniczną reprezentacją ścieżki w ogóle:jar:file:/listener/build/libs/listener-1.0.0-all.jar!/shared/Test.class
.Jestem zaskoczony, widząc, że żaden ostatnio nie zaproponował użycia
Path
. Tu następuje cytat: „ klasy zalicza się różne metody, które mogą być wykorzystane do uzyskania informacji o ścieżce dostępu do elementów toru, konwersja ścieżkę do innych form, albo porcji ekstraktu ścieżki ”Path
Zatem dobrą alternatywą jest uzyskanie
Path
objestów jako:źródło
Jedyne rozwiązanie, które działa dla mnie w systemach Linux, Mac i Windows:
źródło
Miałem ten sam problem i rozwiązałem go w ten sposób:
Mam nadzieję, że ci pomogłem.
źródło
Oto uaktualnienie do innych komentarzy, które wydają mi się niekompletne ze względu na specyfikę
źródło
URLDecoder
do dekodowania znaków specjalnych. W szczególności takie znaki+
zostaną błędnie zdekodowane na spacje. Zobacz moją odpowiedź, aby poznać szczegóły.URLDecoder
, pomimo swojej nazwy, służy do dekodowania adresów URL oraz nazw i wartości parametrów formularzy, a nie adresów URL.Aby uzyskać ścieżkę do uruchomienia pliku jar, przestudiowałem powyższe rozwiązania i wypróbowałem wszystkie metody, które różnią się między sobą. Jeśli te kody działają w środowisku Eclipse IDE, wszyscy powinni być w stanie znaleźć ścieżkę do pliku, w tym wskazaną klasę, i otworzyć lub utworzyć wskazany plik ze znalezioną ścieżką.
Ale jest to trudne, gdy uruchomisz uruchamiany plik jar bezpośrednio lub za pomocą wiersza polecenia, nie powiedzie się, ponieważ ścieżka pliku jar uzyskana z powyższych metod da wewnętrzną ścieżkę w pliku jar, to znaczy zawsze podaje ścieżkę tak jak
rsrc: nazwa-projektu (może powinienem powiedzieć, że jest to nazwa pakietu głównego pliku klasy - wskazanej klasy)
Nie mogę przekonwertować ścieżki rsrc: ... na ścieżkę zewnętrzną, to znaczy, kiedy plik jar jest uruchamiany poza środowiskiem IDE Eclipse, nie może uzyskać ścieżki do pliku jar.
Jedynym możliwym sposobem uzyskania ścieżki uruchamiania pliku jar poza środowiskiem Eclipse IDE jest
ta linia kodu może zwrócić żywą ścieżkę (w tym nazwę pliku) działającego pliku jar (należy zauważyć, że ścieżka powrotu nie jest katalogiem roboczym), ponieważ dokument java i niektóre osoby powiedziały, że zwróci ścieżki wszystkich plików klas w tym samym katalogu, ale jak moje testy, jeśli w tym samym katalogu zawierają wiele plików jar, zwraca tylko ścieżkę do uruchomionego jar (o problemie z wieloma ścieżkami rzeczywiście tak się stało w Eclipse).
źródło
java.class.path
może być wielowartościowy. Jedna z tych wartości z pewnością zapewni katalog lub plik JAR, w którym znajduje się bieżąca klasa, ale który?Inne odpowiedzi wydają się wskazywać na źródło kodu, którym jest lokalizacja pliku Jar, która nie jest katalogiem.
Posługiwać się
źródło
wybrana powyżej odpowiedź nie działa, jeśli uruchomisz słoik, klikając go ze środowiska graficznego Gnome (nie z żadnego skryptu ani terminala).
Zamiast tego polubiłem, że następujące rozwiązanie działa wszędzie:
źródło
URLDecoder
do dekodowania znaków specjalnych. W szczególności takie znaki+
zostaną błędnie zdekodowane na spacje. Zobacz moją odpowiedź, aby poznać szczegóły.NullPointerException
NPE
jeśli w JAR nie będzie żadnych zasobów.Tak naprawdę jest lepsza wersja - stara zawiodła, jeśli nazwa folderu zawierała spację.
Jeśli chodzi o awarie apletów, to i tak zwykle nie masz dostępu do plików lokalnych. Nie wiem dużo o JWS, ale aby obsłużyć lokalne pliki, może nie być możliwe pobranie aplikacji.?
źródło
Próbowałem uzyskać ścieżkę do uruchamiania słoika
c: \ app> java -jar application.jar
Po uruchomieniu aplikacji jar o nazwie „application.jar” w systemie Windows w folderze „ c: \ app ” wartość zmiennej String „folder” wynosiła „ \ c: \ app \ application.jar ” i miałem problemy z testowaniem poprawność ścieżki
Próbowałem więc zdefiniować „test” jako:
aby uzyskać ścieżkę w odpowiednim formacie, takim jak „ c: \ app ” zamiast „ \ c: \ app \ application.jar ” i zauważyłem, że to działa.
źródło
Najprostszym rozwiązaniem jest podanie ścieżki jako argumentu podczas uruchamiania słoika.
Możesz to zautomatyzować za pomocą skryptu powłoki (.bat w Windows, .sh gdziekolwiek indziej):
Kiedyś
.
zdać aktualny katalog roboczy.AKTUALIZACJA
Możesz umieścić plik jar w podkatalogu, aby użytkownicy nie kliknęli go przypadkowo. Twój kod powinien również sprawdzić, aby upewnić się, że argumenty wiersza poleceń zostały dostarczone, i dostarczyć dobry komunikat o błędzie, jeśli argumentów brakuje.
źródło
Musiałem dużo zepsuć, zanim w końcu znalazłem działające (i krótkie) rozwiązanie.
Możliwe, że
jarLocation
pochodzi z przedrostkiem typufile:\
lubjar:file\
, który można usunąć za pomocąString#substring()
.źródło
Ścieżka zawsze odnosi się do zasobu w pliku jar.
źródło
String path = new File(getClass().getResource("").getPath()).getParentFile().getParent(); File jarDir = new File(path.substring(5));
getResource("")
igetResource(".")
nie powiodło się w moich testach, gdy klasa rezydowała w pliku JAR; oba wywołania zwróciły wartość null.NullPointerException
.Działa dobrze w systemie Windows
źródło
Frustrujące jest to, że gdy programujesz w Eclipse,
MyClass.class.getProtectionDomain().getCodeSource().getLocation()
zwraca/bin
świetny katalog, ale kiedy kompilujesz go do jar, ścieżka zawiera/myjarname.jar
część, która daje ci nielegalne nazwy plików.Aby kod działał zarówno w ide, jak i po skompilowaniu go do jar, używam następującego fragmentu kodu:
źródło
Nie jestem do końca pewien co do innych, ale w moim przypadku nie działał z „jarem Runnable” i udało mi się to, naprawiając kody razem z odpowiedzi phchen2 i kolejnej z tego linku: Jak uzyskać ścieżkę do działającego pliku JAR? Kod:
źródło
Wypróbowałem kilka rozwiązań tam, ale żadne nie przyniosło poprawnych wyników dla (prawdopodobnie specjalnego) przypadku, w którym słój działający został wyeksportowany z „Pakowaniem bibliotek zewnętrznych” w Eclipse. Z jakiegoś powodu wszystkie rozwiązania oparte na ProtectionDomain dają w tym przypadku wartość null.
Po połączeniu powyższych rozwiązań udało mi się uzyskać następujący działający kod:
źródło
Spróbuj tego:
źródło
Ta metoda wywołana z kodu w archiwum zwraca folder, w którym znajduje się plik .jar. Powinien działać w systemie Windows lub Unix.
Pochodzi z kodu na: Określ, czy działa z JAR
źródło
Wspomnij, że jest sprawdzany tylko w,
Windows
ale myślę, że działa idealnie na innych systemach operacyjnych [Linux,MacOs,Solaris
] :).Miałem 2
.jar
pliki w tym samym katalogu. Chciałem, aby z jednego.jar
pliku uruchomić drugi.jar
plik, który znajduje się w tym samym katalogu.Problem polega na tym, że po uruchomieniu z
cmd
bieżącego katalogu jestsystem32
.;][[;'57f2g34g87-8+9-09!2#@!$%^^&()
lub()%&$%^@#
działa dobrze.ProcessBuilder
z poniższych poniżej:🍂 ..
🍂
getBasePathForClass(Class<?> classs)
:źródło
Ten kod działał dla mnie:
źródło
Ten kod działał dla mnie w celu identyfikacji, czy program jest wykonywany w pliku JAR lub IDE:
Jeśli muszę uzyskać pełną ścieżkę do pliku JAR systemu Windows, używam tej metody:
Mój pełny kod współpracujący z aplikacją Spring Boot przy użyciu
CommandLineRunner
implementacji, aby aplikacja zawsze była uruchamiana w widoku konsoli (przez pomyłkę dwukrotnie w nazwie pliku JAR), używam następnego kodu:źródło
Piszę w Javie 7 i testuję w Windows 7 w środowisku wykonawczym Oracle, a Ubuntu w środowisku uruchomieniowym open source. Działa to idealnie dla tych systemów:
Ścieżka do katalogu nadrzędnego dowolnego działającego pliku jar (zakładając, że klasa wywołująca ten kod jest bezpośrednim dzieckiem samego archiwum jar):
Zatem ścieżka do pliku foo.jar wyglądałaby następująco:
Ponownie nie zostało to przetestowane na żadnym komputerze Mac lub starszym systemie Windows
źródło
getProtectionDomain
Podejście może nie działać czasami przykład gdy trzeba znaleźć słoik dla niektórych klas java bazowych (np w moim przypadkuStringBuilder
klasy w IBM JDK), jednak płynnie następujące prace:źródło
Mam inny sposób, aby uzyskać lokalizację ciągu klasy.
Łańcuch wyjściowy będzie miał postać
Spacje i inne znaki są obsługiwane w formie bez
file:/
. Więc będzie łatwiejszy w użyciu.źródło