Daten aus Jar laden

Network

Top Contributor
Hi,

selbstverständlich gibt es dazu sehr viel über Google zu finden, aber irgendwie kriege ich es nicht hin.

Die Datenstruktur sieht so aus:
Code:
Ordner/
     Programm.jar/
          Bilder/
               [Bilder]
     Bilder/
          [Bilder]
Der Ordner mit den Bildern ist also sowohl in der Jar als auch nochmals außerhalb dieser.

Nun versuche ich mit
Java:
URL url = this.getClass().getResource(file);
BufferedImage bfimg;
bfimg = ImageIO.read(url);
ein Bild zu laden. Es schlägt fehl, es kommt eine
IllegalArgumentException: input == null
Nach Dokumentation bedeutet das, dass URL == null ist.

Und nur um mir diese Gegenfrage zu ersparen: Das Bild existiert
Vorher habe ich die Bilder einfach aus dem Bilder Odner erfolgreich geladen mit
Java:
ImageIO.read(new File( file ));
Der Dateiname hat sich nicht geändert.

Noch eine Zusatz an Information:
this.getClass().getResource(); wird in einer Jar Datei in der eigentlichen Jar Datei aufgerufen. Ich nehme an der Fehler könnte hier liegen, da er dann in der Jar der Jar sucht (eventuell?).

Irgendwelche Lösungsvorschläge?

Vielen Dank 🙂
Gruß
Net
 
Zuletzt bearbeitet:
schon mal was von DEBUGGING gehört ? lass dir "url" doch einfach mal mit nem sysout ausgeben anstatt hier gleich n topic aufzumachen ...
 
Tröööt dein "Genie" hat mal wieder zugeschlagen. Das nächste mal wenn du nichts produktives zu sagen hast, geh einfach bitte wieder.

Aber alle guten Dinge sind drei! In der Dokumentation steht das:
Nach Dokumentation bedeutet das, dass URL == null ist.
t
Im SourceCode von ImageLoader steht das
Und jetzt sogar in meinem kleinen Konsolenfenster
Code:
null

Naja ich lasse jetzt dem ImageLoader die Klasse übergeben der Datei die ein Bild anfordert.
So werden die Bilder aus dem richtigen Verzeichnis geladen.
Jetzt müssen wohl einige ihren Code updaten.
 
Die Variable "file" würd' ich zu gerne sehen... oder Moment, Glaskugel sagt: "bild.png". Müsste aber "/Bilder/bild.png", "./Bilder/bild.png" oder "Bilder/bild.png" heissen. Ressourcepfade sind klassenpfadrelativ.
[EDIT]Im übrigen ging mir dieses "URL-File-Ressource-Bläh-Ta-Taig" irgend wann auch mal dermaßen auf den... naja zumindest kam so etwas bei raus.
http://www.java-forum.org/allgemein...ve-pfade-arbeitsverzeichnisse.html#post956646[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:
Tröööt dein "Genie" hat mal wieder zugeschlagen. Das nächste mal wenn du nichts produktives zu sagen hast, geh einfach bitte wieder.

Aber alle guten Dinge sind drei! In der Dokumentation steht das:

Im SourceCode von ImageLoader steht das

Und jetzt sogar in meinem kleinen Konsolenfenster
Code:
null

Naja ich lasse jetzt dem ImageLoader die Klasse übergeben der Datei die ein Bild anfordert.
So werden die Bilder aus dem richtigen Verzeichnis geladen.
Jetzt müssen wohl einige ihren Code updaten.

gut ... und was macht man wenn man weis das die exception bedeutet das der parameter NULL ist ?

normalerweise würde man jetzt anfangen zu gucken WARUM der parameter NULL ist ... was auch unter den "debugging" fällt ...

und da du ja so verbissen auf die DOC bist hier die antwort
Returns:A URL object or null if no resource with this name is found
ergo : es wurde keine resource mit dem übergebenen namen gefunden ...
also lässt man sich den parameter von getResource() mal mit sysout ausgeben und prüft ob dieser richtig ist ...

wie Spacerat schon sagte sucht ClassLoader.getResource() an die Class.getResource() delegiert relativ zur klasse ...

wenn die klasse also im JAR unter "/Klasse.class" zu finden ist und man nur "bild.png" übergibt sucht der CL nach "/bild.png" ... was bei dir aber falsch wäre ... du müsstest stattdessen "/Bilder/bild.png" übergeben ...
ist zwar absolut zum jar-root ... und hier würde auch relativ "Bilder/bild.png" reichen ... aber es empfiehlt sich immer zum jar-root absolut anzugeben wenn man sich nicht ganz sicher ist wo nachher was landet ...
 
Vielen Dank erstmal, jetzt kommt das ins Rollen und verstehe warum das Thema so eklig ist.
"Weil es zu oft gefragt wird".
Das dachte ich mir schon ein bisschen nach meiner rumgoogelei. Scheint ja auch eins der ersten Dinge zu sein die sich Anfänger allgemein aneignen.

Habe versucht dem immer aus dem Weg zu gehen und die Bilder in einem extra Ordner zu lagern, aber manch einer mag das anscheinend nicht, weshalb ich dazu angehalten wurde genau das zu verändern.

Das Problem ist wie gesagt, dass die Bilder/Daten ladende Klasse eigentlich nochmals selbst als Library in der Jar liegt. Entweder das oder ich übersehe das einfachste.
Deshalb meine Frage ob jemand weiss was man in diesem Falle coden muss.
Umgedreht funktioniert es genauso nicht, also wenn sich die Bilder in einer jar der jar befinden, und die ladende Klasse nur in der Jar, wobei man hier einfach den erweiterten Pfad angibt.
Es funktioniert aber wenn ich von einer Klasse getClass() aufrufe die sich in der selben Jar aufhält - logischerweise.

Das ist natürlich ärgerlich, ich habe den SourceCode durchforstet um nach einer "Lücke"/Workaround zu suchen, aber nichts gefunden bis jetzt.

Und zum Abschluss: Werde ich jetzt 2 Codes zeigen mit folgender komplettierter Datenstruktur:
Code:
Ordner/
     Programm.jar/
          Engine.jar    // Lädt die Bilddatei
          Bilder/
               [Bilder]
     Bilder/
          [Bilder]

Code 1 - IllegalArgumentException
Java:
String file = "Bilder/TestBild.png";
URL url = this.getClass().getResource(file);
BufferedImage bfimg;

System.out.println( url ); // -> null
bfimg = ImageIO.read(url);
System.out.println( "Image loaded" ); // [not called]

Code 2
Java:
String file = "Bilder/TestBild.png";
File f = new File(file);
BufferedImage bfimg;

System.out.println( f.exists() ); // -> true
bfimg = ImageIO.read(f);
System.out.println( "Image loaded" ); // -> Image loaded

Vielen Dank 🙂
Gruß
Net

PS: Was mich auch wundert: Ich dachte (so hatte ich es gelesen) wenn getResource() nichts findet, wird der Ordner indem sich die Jar befindet danach durchsucht.

[EDIT]
Und danke für den "/"-Unterschied. Wusste nicht dass das ein Unterschied macht, hatte es zwar gelesen wobei eher "überlesen". Wird mir in Zukunft sicherlich von Nützen sein. In diesem Fall glaube ich nicht, bin auf Nummer Sicher gegangen und habe die Pfade entsprechend angepasst.
[/EDIT]
 
Zuletzt bearbeitet:
das sind solche dinge wo ich am liebsten einfach nur hierauf verweisen würde : http://www.java-forum.org/forum-faq-beitraege/7407-man-fragen-richtig-stellt.html

solche wichtigen dinge ... wie eben das man JAR-IN-JAR verwendet ... werden leider von den meisten anfängern verschwiegen ... entweder weil sie denken das es daran nicht liegen kann oder weil sie nicht wissen das es mit sowas probleme gibt ..

grundsätzlich gilt : JAR-IN-JAR erfordert spezielle ClassLoader-implementierungen ...
es gibt zwar entsprechende tools im netz ... und IDEs können auch sog. "FAT-JARs" bauen ... also alles aus den source-JARs extrahieren und zu einem großen kompletten JAR wieder zusammen setzen ...
es ist halt ein etwas anspruchvolleres thema und längst nicht so banal wie man denkt ... auch weit fortgeschrittene java-entwickler haben damit immer mal wieder so ihre probleme wenn sie sich mit sowas noch nicht beschäftigt haben ...

als einfach lösung würde ich also ein "FAT-JAR" vorschlagen ... also das nachher am ende ALLE dateien in einer einzigen JAR liegen ... ohne das die JAR selbst noch weitere JARs enthält ... deine IDE sollte das auf die reihe bekommen (so fern du denn eine nutzt) ...

eine weitere möglichkeit wäre wenn man die JARs nicht alle in einem JAR zusammenpackt ... sondern sie ins FileSystem neben das main-JAR legt ... also das es dann z.b. so aussieht
Code:
/dir
/dir/main.jar
/dir/support.jar
/dir/lib.jar
/dir/resource.jar
und dann im manifest den parameter "Class-Path" richtig setzt ...
natürlich kann man bei dieser variante die zusatz-JARs noch in einem unterordner organisieren ...

die letzte "einfache" möglichkeit wäre vor dem laden halt die JARs in TEMP zu extrahieren und dann im FileSystem auf diese zuzugreifen ... das würde dann mit nem URLClassLoader gehen

die wirkliche "königsdiziplin" wäre dann am ende ein "JarInJarClassLoader" der es halt ermöglicht beliebig rekursiv durch die in der aktuellen JAR enthalten JARs geht und resourcen laden kann ... sowie von anfragen von "tieferen ebenen" nach resourcen die in "höheren ebene" liegen beantworten und laden kann ...
stichwort dazu wie schon gesagt : jar-in-jar classloader ...

natürlich muss dann der code entsprechend angepasst werden ... und funktioniert auch nur mit libs die sowas unterstützen ...
 
Ah okay vielen Dank.

Also das "Jar in Jar" steht bereits ganz oben in meiner Anfangsfrage.
Hatte sogar darauf hingewiesen, dass ich denke, dass es sich hierbei um den Fehler handelt.
Google liefert mir dafür aber nur Müll (Ich weisse darauf hin, dass die Googlesuche an die einzelnen Benutzer angepasst ist).

Eclipse bietet zwar ein "Extract requierd libraries into generated JAR" an, das ist aber leider in diesem Fall nicht möglich. Lizenzierungen n stuff.
Aber vielen Dank. Jetzt weiss ich auf jedenfall, dass es nicht so einfach ist.

Das macht es geistig schon ein bisschen einfacher und klarer 🙂
Dann habe ich ja eigentlich auch gute Argumente, dass beim laden von Daten die Klasse mit angegeben werden muss. Wenn es ohne größeren Aufwand nicht anderst geht. 🙂

Vielen Dank
Gruß
Net

PS: Ich entschuldige mich für den rauen Ton von mir, Tröööt. Hatte mich eine Minute vorher mit einem Kollegen herumgeschlagen - eine gute halbe Stunde - der so absolut nervtötend abweisend war im Sinne von "Oh sorry, what was the matter again?" das ich ein bisschen am Rande der Verzweiflung in dem Moment war. Jetzt sind meine Nerven wieder beieinander. 😀
 
Jetzt sind meine Nerven wieder beieinander. 😀
Du Glücklicher...
Die wahre Königsdisziplin bringt mich grad' an den Rand der Verzweiflung - beliebige Daten aus beliebiger Quelle (inkl. Jar-In-Jar) standardtisiert laden. Nix da mit File hier, String dort, URL anderswo und InputStream LMAA... Eine einzige statische Anweisung soll's werden.
Ich muss das endlich auf die Reihe kriegen. Das Projekt entpuppt sich aber anscheinend als Lebensaufgabe.
 
@TO
ja .. ich habs auch noch gelesen ... aber irgendwie völlig verpeilt ... mein fehler ... passiert jedem mal ..

wenn es wegen lizenzen nicht ein fat-jar zu bauen solltest du auf jeden fall die variante nutzen nur deine klassen im jar zu haben ... alle abhängigkeiten solltest du in einen ordner "lib" packen der im selben ordner wie dein jar liegt und darin alle anderes jars ablegen ...

ich weis jetzt nicht aus dem stehgreif ob man so im manifest nur "lib" als ordner angeben muss oder jedes einzelne jar ... letzteres würde ich aber empfehlen ...

@Spacerat
wäre schön wenn du dazu mal an passender stelle im forum n thread auf machst und dort mal den code postest ... wäre nämlich sehr interessant und würde gerne mit dran arbeiten ...
 
@Spacerat
wäre schön wenn du dazu mal an passender stelle im forum n thread auf machst und dort mal den code postest ... wäre nämlich sehr interessant und würde gerne mit dran arbeiten ...
Schon oft geschehen... datatypeslibrary - reading first come along files with only one instruction - Google Project Hosting
Einfach mal nach suchen.
z.B.
http://www.java-forum.org/spiele-mu...886-vorstellung-hotsound-meinung-gefragt.html
http://www.java-forum.org/awt-swing-javafx-swt/145047-gif-macht-mir-probleme.html
 

Zurück
Oben