Ładuję plik tekstowy z pakietu w skompilowanym pliku JAR mojego projektu Java. Odpowiednia struktura katalogów jest następująca:
/src/initialization/Lifepaths.txt
Mój kod ładuje plik, wywołując Class::getResourceAsStream
a InputStream
.
public class Lifepaths {
public static void execute() {
System.out.println(Lifepaths.class.getClass().
getResourceAsStream("/initialization/Lifepaths.txt"));
}
private Lifepaths() {}
//This is temporary; will eventually be called from outside
public static void main(String[] args) {execute();}
}
Wydruk zawsze będzie drukowany null
, bez względu na to, z czego korzystam. Nie jestem pewien, dlaczego powyższe nie działa, więc próbowałem też:
"/src/initialization/Lifepaths.txt"
"initialization/Lifepaths.txt"
"Lifepaths.txt"
Żadna z tych prac. Do tej pory przeczytałem wiele pytań na ten temat, ale żadne z nich nie było pomocne - zwykle mówią tylko, aby ładować pliki przy użyciu ścieżki katalogu głównego, co już robię. To lub po prostu załaduj plik z bieżącego katalogu (po prostu załaduj filename
), co również próbowałem. Plik jest kompilowany do pliku JAR w odpowiednim miejscu o odpowiedniej nazwie.
Jak to rozwiązać?
Lifepaths.class
. Biorąc to pod uwagę, dlaczegogetClassLoader()
pozwala to działać? (Napisz też odpowiedź!)Lifepaths.getClass()
? Nie ma takiej statycznej metody zdefiniowanej w Object ...getResource(String)
. BTW - Zawsze miałem problemy z nakłonieniem któregokolwiek z nich do pracy wstatic
kontekście. Problem polega na tym, że uzyskany moduł ładujący jest przeznaczony dla klas J2SE. Musisz uzyskać dostęp do modułu ładującego klasy kontekstu, który jest przeznaczony dla samej aplikacji.Odpowiedzi:
Lifepaths.class.getClass().getResourceAsStream(...)
ładuje zasoby za pomocą modułu ładującego klasy systemowe, oczywiście kończy się niepowodzeniem, ponieważ nie widzi plików JARLifepaths.class.getResourceAsStream(...)
ładuje zasoby przy użyciu tego samego modułu ładującego, który załadował klasę Lifepaths i powinien mieć dostęp do zasobów w twoich plikach JARźródło
/
przed ścieżką, jeśli plik znajduje się w innym katalogu; na przykładinitialization/Lifepaths.txt
. Jeśli ścieżka do pliku jest taka sama jak klasa yout (ale w zasobach jak główny katalog), możesz po prostu umieścić nazwę pliku bez żadnej/
. Na przykład, jeśli twoja klasa ma następującą ścieżkęsrc/main/java/paths/Lifepaths.java
, twój plik musi mieć tę ścieżkęsrc/main/resources/paths/Lifepaths.txt
.Reguły są następujące:
I próbuj:
zamiast
(nie jestem pewien, czy to robi różnicę, ale ten pierwszy użyje poprawnego ClassLoadera / JAR, podczas gdy nie jestem pewien co do tego drugiego)
źródło
Istnieje więc kilka sposobów na uzyskanie zasobu ze słoika, a każdy z nich ma nieco inną składnię, w której ścieżka musi być określona inaczej.
Najlepszym wyjaśnieniem, jakie widziałem, jest ten artykuł z JavaWorld . Podsumuję tutaj, ale jeśli chcesz dowiedzieć się więcej, zapoznaj się z tym artykułem.
Metody
1)
ClassLoader.getResourceAsStream()
.Format: „/” - rozdzielone nazwy; bez wiodących znaków „/” (wszystkie nazwy są bezwzględne).
Przykład:
this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
2)
Class.getResourceAsStream()
Format: „/” - rozdzielone nazwy; wiodące „/” oznacza nazwy bezwzględne; wszystkie inne nazwy odnoszą się do pakietu klasy
Przykład:
this.getClass().getResourceAsStream("/some/pkg/resource.properties");
źródło
Nie używaj ścieżek bezwzględnych, uczyń je względnymi do katalogu „resources” w swoim projekcie. Szybki i brudny kod wyświetlający zawartość MyTest.txt z katalogu „resources”.
źródło
Możesz spróbować tego, aby uzyskać strumień, tj. Najpierw pobierz adres URL, a następnie otwórz go jako strumień.
Kiedyś miałem podobne pytanie: odczyt pliku TXT ze słoika kończy się niepowodzeniem, ale odczyt obrazu działa
źródło
Wygląda na to, że występuje problem z używanym programem ClassLoader. Użyj kontekstuClassLoader, aby załadować klasę. Jest to niezależne od tego, czy jest to metoda statyczna / niestatyczna
Thread.currentThread().getContextClassLoader().getResourceAsStream
......źródło
Znalazłem się w podobnym problemie. Ponieważ używam maven, musiałem zaktualizować plik pom.xml, aby zawierał coś takiego:
Zanotuj tam znacznik zasobów, aby określić, gdzie znajduje się ten folder. Jeśli zagnieżdżałeś projekty (tak jak ja), możesz chcieć uzyskać zasoby z innych obszarów zamiast tylko w module, w którym pracujesz. Pomaga to ograniczyć utrzymywanie tego samego pliku w każdym repozytorium, jeśli używasz podobnych danych konfiguracyjnych
źródło
Dla mnie zadziałało dodanie pliku,
My Project/Java Resources/src
a następnie użycieNie musiałem jawnie dodawać tego pliku do ścieżki (dodanie go
/src
najwyraźniej robi to)źródło
Nie wiem czy pomogę, ale w moim przypadku miałem swój zasób w folderze / src / i otrzymywałem ten błąd. Następnie przeniosłem zdjęcie do folderu bin i to rozwiązało problem.
źródło
Upewnij się, że katalog zasobów (np. „Src”) znajduje się w ścieżce klasy (upewnij się, że jest to katalog źródłowy na ścieżce kompilacji w środowisku Eclipse).
Upewnij się, że clazz jest ładowany z głównego modułu ładującego klasy.
Następnie, aby załadować src / initialization / Lifepaths.txt, użyj
Dlaczego:
clazz.getResourcesAsStream(foo)
wyszukuje foo ze ścieżki klasy clazz w stosunku do katalogu, w którym mieszka clazz . Wiodące „/” powoduje, że ładuje się z katalogu głównego dowolnego katalogu w ścieżce klas clazz.O ile nie jesteś w jakimś kontenerze, takim jak Tomcat, lub nie robisz czegoś bezpośrednio z ClassLoaders, możesz po prostu traktować swoją ścieżkę klas zaćmienia / linii poleceń jako jedyną ścieżkę klasy programu ładującego klasy.
źródło
Domyślną JVM ClassLoader użyje rodzic-classloader załadować zasobów pierwszy: .
Lifepaths.class.getClass()
Classloader jestbootstrap classloader
, więcgetResourceAsStream
przeszukuje tylko $ JAVA_HOME, niezależnie od podanego użytkownikaclasspath
. Oczywiście Lifepaths.txt nie ma.Lifepaths.class
Classloader jestsystem classpath classloader
, więcgetResourceAsStream
będzie wyszukiwał zdefiniowane przez użytkownikaclasspath
i Lifepaths.txt tam jest.Podczas używania
java.lang.Class#getResourceAsStream(String name)
nazwa, która nie zaczyna się od „/”, zostanie dodanapackage name
jako prefiks. Jeśli chcesz tego uniknąć, skorzystaj zjava.lang.ClassLoader#getResourceAsStream
. Na przykład:źródło
Z grubsza mówiąc:
getClass().getResource("/")
~ =Thread.currentThread().getContextClassLoader().getResource(".")
Załóżmy, że struktura projektu wygląda następująco:
źródło
jeśli używasz Maven, upewnij się, że twoje opakowanie to „jar”, a nie „pom”.
źródło
To, czego naprawdę potrzebujesz, to pełna bezwzględna ścieżka klasy dla pliku. Zamiast zgadywać, spróbuj znaleźć ROOT, a następnie przenieś plik do lepszej lokalizacji, bazowej struktury plików <.war> ...
źródło
Dla mnie zadziałało, że umieściłem plik
i
źródło
src/main/JAVA
, oczywiście nie należy tutaj umieszczać plików innych niż kodowe.@Emracool ... Proponuję ci alternatywę. Ponieważ wydaje się, że próbujesz załadować plik * .txt. Lepiej używać
FileInputStream()
raczej niż tego denerwującegogetClass().getClassLoader().getResourceAsStream()
lubgetClass().getResourceAsStream()
. Przynajmniej twój kod wykona się poprawnie.źródło