Jak uzyskać bezwzględną ścieżkę do pliku w folderze / resources projektu

98

Załóż standardową konfigurację Mavena.

Powiedz w folderze zasobów, że masz plik abc.

W Javie, jak mogę uzyskać bezwzględną ścieżkę do pliku?

James Raitsev
źródło
Czy chcesz napisać wtyczkę Maven? Czy chcesz uzyskać dostęp do pliku podczas wykonywania programu?
Gyro Gearless
Istnieją trzy warianty rozwiązania, w zależności od sytuacji: stackoverflow.com/a/56327069/715269
Gangnus

Odpowiedzi:

75

Możesz użyć ClassLoader.getResourcemetody, aby uzyskać właściwy zasób.

URL res = getClass().getClassLoader().getResource("abc.txt");
File file = Paths.get(res.toURI()).toFile();
String absolutePath = file.getAbsolutePath();

LUB

Chociaż może to nie działać przez cały czas, prostsze rozwiązanie -

Możesz stworzyć Fileobiekt i użyć getAbsolutePathmetody:

File file = new File("resources/abc.txt");
String absolutePath = file.getAbsolutePath();
Rahul Bobhate
źródło
8
Porada dotycząca ograniczonego użycia, ponieważ katalog roboczy jest katalogiem głównym maven. I nawet wtedy powinieneś raczej używać target/classes/abc.txtjako odniesienia do pliku, ponieważ jest to kanoniczne miejsce, w którym Maven umieszcza pliki zasobów po przetworzeniu (na przykład wtyczka maven-resources mogła wykonać podstawienie właściwości w abc.txt). Znacznie lepiej jest użyć abc.txt poprzez getResource () ze ścieżki klas.
Gyro Gearless
3
Co się stanie, jeśli użytkownik końcowy uruchamia Twoją aplikację jako wykonywalny plik JAR? Wtedy w ogóle nie będzie fizycznego pliku. To kolejny powód, dla którego powinieneś użyć metody getResource () i np. Otworzyć do niej strumień wejściowy w zależności od tego, co chcesz z nią zrobić.
Matthew Wise,
6
Czy można to usunąć jako poprawną odpowiedź? @Karol S odpowiedział poniżej - to powinna być poprawna odpowiedź (stąd rozbieżność głosów pozytywnych)
DanGordon
3
Zła odpowiedź. Proszę zapoznać się z poniższą odpowiedzią @Karol
bhathiya-perera
171

Właściwy sposób, który faktycznie działa:

URL resource = YourClass.class.getResource("abc");
Paths.get(resource.toURI()).toFile();

Nie ma teraz znaczenia, gdzie fizycznie znajduje się plik w ścieżce klas, zostanie znaleziony, o ile zasób jest w rzeczywistości plikiem, a nie wpisem JAR.

(Pozornie oczywiste new File(resource.getPath())nie działa dla wszystkich ścieżek! Ścieżka jest nadal zakodowana w adresie URL!)

Karol S
źródło
5
Lub przypuszczalnie mógłbyś po prostu zrobić: new File(resource.toURI()).getAbsolutePath();(tj. Nie sądzę, że potrzebujesz obiektu Path?)
Dan King
1
Dobra wskazówka na temat metody toURI (), pozwala to uniknąć spacji na ścieżce wychodzących jako% 20!
Matthew Wise
29
Dzięki! To prawie zadziałało dla mnie. Ale musiałem dokonać jednej zmiany: YourClass.class.getClassLoader (). GetResource ("abc");
yngwietiger
Możesz alternatywnie zrobić, new File(YourClass.class.getResource("abc").toURI().getPath())jeśli chcesz.
Mike Rylander
3
Nie rozumiem, jak to zadziałało dla tak wielu ludzi bez początkowego ukośnika:.getResource("/abc")
cahen,
29

Musisz określić ścieżkę zaczynającą się od /

URL resource = YourClass.class.getResource("/abc");
Paths.get(resource.toURI()).toFile();
Hett
źródło
12

Utwórz instancję classLoader klasy, której potrzebujesz, aby uzyskać łatwy dostęp do plików lub zasobów. teraz masz dostęp do ścieżki używając getPath()metody tej klasy.

 ClassLoader classLoader = getClass().getClassLoader();
 String path  = classLoader.getResource("chromedriver.exe").getPath();
 System.out.println(path);
Kirit Thakrar
źródło
1

Aby zwrócić plik lub ścieżkę do pliku

URL resource = YourClass.class.getResource("abc");
File file = Paths.get(resource.toURI()).toFile(); // return a file
String filepath = Paths.get(resource.toURI()).toFile().getAbsolutePath();  // return file path
Emmanuel Osimosu
źródło
0

Na naszej drodze do ścieżki absolutnej są dwa problemy:

  1. Znalezione miejsce docelowe nie będzie miejscem, w którym znajdują się pliki źródłowe, ale miejscem zapisania klasy. A folder zasobów prawie na pewno będzie znajdować się gdzieś w folderze źródłowym projektu.
  2. Te same funkcje do pobierania zasobów działają inaczej, jeśli klasa działa we wtyczce lub w pakiecie bezpośrednio w obszarze roboczym.

Poniższy kod da nam wszystkie przydatne ścieżki:

    URL localPackage = this.getClass().getResource("");
    URL urlLoader = YourClassName.class.getProtectionDomain().getCodeSource().getLocation();
    String localDir = localPackage.getPath();
    String loaderDir = urlLoader.getPath();
    System.out.printf("loaderDir = %s\n localDir = %s\n", loaderDir, localDir);

Tutaj badane są obie funkcje, których można użyć do lokalizacji folderu zasobów. Co do tego class, można to uzyskać w dowolny sposób, statycznie lub dynamicznie.


Jeśli projektu nie ma we wtyczce, kod, jeśli zostanie uruchomiony w JUnit, wydrukuje:

loaderDir = /C:.../ws/source.dir/target/test-classes/
 localDir = /C:.../ws/source.dir/target/test-classes/package/

Tak więc, aby dostać się do src / rest / resources, powinniśmy poruszać się w górę iw dół drzewa plików. Można zastosować obie metody. Zauważ, że nie możemy użyć getResource(resourceFolderName), ponieważ ten folder nie znajduje się w folderze docelowym. Mam nadzieję, że nikt nie umieszcza zasobów w utworzonych folderach.


Jeśli klasa znajduje się w pakiecie znajdującym się we wtyczce, wynikiem tego samego testu będzie:

loaderDir = /C:.../ws/plugin/bin/
 localDir = /C:.../ws/plugin/bin/package/

Więc znowu powinniśmy poruszać się w górę iw dół drzewa folderów.


Najciekawszy jest przypadek, gdy pakiet jest uruchamiany we wtyczce. Jako test wtyczki JUnit, na przykład. Wynik to:

loaderDir = /C:.../ws/plugin/
 localDir = /package/

Tutaj możemy uzyskać ścieżkę bezwzględną tylko łącząc wyniki obu funkcji. I to nie wystarczy. Pomiędzy nimi należy umieścić ścieżkę lokalną miejsca, w którym znajdują się pakiety klas, względem folderu wtyczek. Prawdopodobnie będziesz musiał wstawić coś jako srclub src/test/resourcetutaj.

Możesz wstawić kod do swojego i zobaczyć ścieżki, które masz.

Gangnus
źródło