# Laden einer (Resourcendatei) aus einem Jar-File



## HarryR (29. Nov 2017)

Hallo,

ich bin neu im Forum und grüße euch alle.

Ich programmiere eigentlich schon eine Weile mit Java,
Google ist mein Freund, wenn ich nicht weiter weiß.

Aber in diesem Fall hat mir auch Freund Google nicht helfen können.

So, erst mal die Randbedingungen, ich verwende als Dev-Oberfläche
Eclipse Oxygen.1a Release (4.7.1a)

Worum es in meinem Programm geht ist nebensächlich,
das Feature was nicht klappt ist das laden eines Resourcefiles.

Aus Eclipse heraus klappt alles wunderbar, die Datei wird gefunden,
Parameter werden ausgelesen, fertig.

Da mein Programm aber natürlich auch außerhalb der IDE funktionieren soll lasse ich Eclipse eine JAR-Datei generieren. Ich habe nach einigen Versuchen das Modell
"Extract required libraries into generated JAR" als das beste befunden und verwende es daher auch.

So, die bewusste Konfigurationsdatei settings.txt befindet sich im
gleichen Verzeichnis wie die Quelltext *.Java-Dateien.

Im JAR-File befindet sie sich in 
"jar:file:/C:/test/myproject.jar!/PACKAGENAME/settings.txt"

Das ergibt folgender Aufruf
System.out.println(settings.*class*.getResource("settings.txt").toString());

settings ist die Klasse, die (ihre) Resourcedatei laden soll.

So weit so gut, ich weiß also, das die Datei prinzipiell auffindbar ist. Es ist auch bekannt, dass sie sich innerhalb des JAR-Files befindet, aber wenn ich mir einen InputStream basteln will scheitere ich bisher bei allen Versuchen (also mit Slashes, vorangestelltem Pfad etc).

Nach Aufruf von
Inputstream stream = settings.*class*.getResourceAsStream("settings.txt");
ist stream immer = null

Ich habe schon viel gefunden und ausprobiert, leider hatte ich bisher keinen Erfolg.

Seht ihr woran es liegt ?
Viele Grüße Harry


----------



## mrBrown (29. Nov 2017)

HarryR hat gesagt.:


> So, die bewusste Konfigurationsdatei settings.txt befindet sich im
> gleichen Verzeichnis wie die Quelltext *.Java-Dateien.


Befindet sich die Datei denn in der jar (die kannst du einfach als zip entpacken)?


----------



## HarryR (29. Nov 2017)

mrBrown hat gesagt.:


> Befindet sich die Datei denn in der jar (die kannst du einfach als zip entpacken)?


Ja, ich habe natürlich mit meinem Lieblingstool, dem TotalCommander reingeschaut
(nachdem ich in *.jar *.tar umbenannt habe). Sie befindet sich im "Package"-Verzeichnis bei den *.class-Dateien der
diversen anderen Klassen (also auch settings.class aus der heraus ich die Datei ja laden will).
Grüßle


----------



## Harry Kane (29. Nov 2017)

Bei mir funktioniert in der Klasse mainpackage.subpackage folgendes

```
java.net.URL url = getClass().getResource("/resources/test.config");
```
Das "resources"-Verzeichnis liegt im selben Verzeichnis wie mainpackage, d. h. "resources" und "mainpackage" haben denselben parent.


----------



## RalleYTN (29. Nov 2017)

```
InputStream in = this.getClass().getClassLoader().getResourceAsStream("mein/gesamter/package/path/innerhalb/der/jar/datei.txt");
```
Sollte auf allen Systemen funktionieren so.
Wenn du jetzt also das Package "de.meinname.meinprodukt.meinpackage" mit der Datei "settings.txt" drinne hättest dann wäre der Parameter für getResourceAsStream "de/meinname/meinprodukt/meinpackage/settings.txt".


----------



## mrBrown (29. Nov 2017)

HarryR hat gesagt.:


> settings.*class*.getResourceAsStream("settings.txt");


Dieser aufruf sieht richtig aus (und sollte das gleiche wie mit ClassLoader und vollem Pfad oder vorangestellten Slash und voller Pfad sein).

Kannst du einmal deine Packagestruktur zeigen?


----------



## HarryR (30. Nov 2017)

Harry Kane hat gesagt.:


> Bei mir funktioniert in der Klasse mainpackage.subpackage folgendes
> 
> ```
> java.net.URL url = getClass().getResource("/resources/test.config");
> ...



Ja, getResource() funktioniert ja bei mir auch, aber den InputStream für die Resource bekomme ich nicht hin.


----------



## mrBrown (30. Nov 2017)

Dann öffne doch den Stream mal direkt über die URL, dann bekommst du die Exception mit, die möglicherweise fliegt


----------



## HarryR (30. Nov 2017)

Der Hammer, ich glaube wir wären nie drauf gekommen.
Die Lösung ist sowas von .. crazy.

Erst mal, die Lösung von RalleYTN ist korrekt,
so habe ich es auch die ganze Zeit probiert, es hat aber nie funktioniert.


Ich habe eben folgendes gemacht (im Output sind ein paar Debugzeilen):

```
c:\tmp\!!!!>java -jar mein.jar
classpath=mein.jar
Resourcepath: jar:file:/C:/tmp/!!!!/mein.jar!/PACKAGENAME/settings.txt
TYP: JAR
stream: null
```

Man sieht es gibt keinen Stream (null-Pointer)

Dann wollte ich euch den Stand der Dinge zusenden , fand aber
den Namen meines Testverzeichnis doof und habe daher in einem anderem Verzeichnis getestet
Also :


```
c:\tmp\!!!!>cd ..
c:\tmp>cd pzd
c:\tmp\pzd>java -jar mein.jar
classpath=mein.jar
mein.jar
Resourcepath: jar:file:/C:/tmp/pzd/mein.jar!/PACKAGENAME/settings.txt
TYP: JAR
stream: sun.net.[URL='http://www.protocol.jar.JarURLConnection$JarURLInputStream@27c170f0']www.protocol.jar.JarURLConnection$JarURLInputStream@27c170f0[/URL]
```

Voila, stream ist da (!= null), funktioniert also.
Wo liegt das Problem ?
Im Verzeichnisnamen "!!!!".

getResourceAsStream() scheint wenn es die Resource sucht
intern getResource() zu verwenden, der Resourcenpfad ist aber in meinem Fall

```
jar:file:/C:/tmp/!!!!/mein.jar!/PACKAGENAME/settings.txt
```

Da findet sich weit vorne wohl der Delimiter "!",
der den Beginn des Pfades IM Jar-File anzeigen sollte,
aber hier schon im Pfad zum JAR-File auftaucht.
So wird natürlich die Resource nicht gefunden.

Ob ich das als Fehler in der Implementierung bezeichnen kann ?!
Auf jeden Fall wäre es evtl. besser die Suche nach dem Delimiter von hinten zu beginnen,
das wird abner scheitern, wenn der Packagename oder die Resource ein "!" enthält.

So, danke für die Hilfe.

Grüßle
Harry


----------



## HarryR (30. Nov 2017)

Mhh, das mit den Codezeilen hat irgendwie nicht funktioniert.
Was habe ich da falsch gemacht ?

Grüßle
Harry


----------



## SchwarzWeiß (30. Nov 2017)

HarryR hat gesagt.:


> Mhh, das mit den Codezeilen hat irgendwie nicht funktioniert.
> Was habe ich da falsch gemacht ?


Probier mal ohne Leerzeichen vor und hinter dem = bei code = java


----------



## mrBrown (30. Nov 2017)

Das ist ein bekannter Bug, der leider vermutlich nie gefixt wird, weil dann alles mögliche Brechen würde :/


----------



## HarryR (30. Nov 2017)

Bekannter Bug .. schade, mich hat er zwei Tage und ein paar Resthaare gekostet .. grrrrrrr


----------



## Flown (30. Nov 2017)

@mrBrown Hast du das Ticket bei der Hand (wäre super wenn man das verlinken könnte)?


----------



## mrBrown (30. Nov 2017)

z.B. dies: http://bugs.java.com/view_bug.do?bug_id=4523159


----------



## HarryR (30. Nov 2017)

mrBrown hat gesagt.:


> z.B. dies: http://bugs.java.com/view_bug.do?bug_id=4523159


Wow, da feiern wir ja bald den silbernen Bugtag )
Ich gebe ja zu dass das eine subtile Geschichte ist,
aber sich so lange um eine gescheite Lösung zu drücken ist
schon ein Ding ....


----------



## pcfreak9000 (1. Dez 2017)

HarryR hat gesagt.:


> Der Hammer, ich glaube wir wären nie drauf gekommen.
> Die Lösung ist sowas von .. crazy.
> 
> Erst mal, die Lösung von RalleYTN ist korrekt,
> ...



ich dachte Windoof verbietet spezielle Sonderzeichen (auch !) in Datei- und Ordnernamen?


----------



## mrBrown (1. Dez 2017)

pcfreak9000 hat gesagt.:


> Windoof


Grad Frühstückspause in der Schule?



pcfreak9000 hat gesagt.:


> ich dachte _Windows_ verbietet spezielle Sonderzeichen (auch !) in Datei- und Ordnernamen?


Nein, ! nicht.
Der Fehler würde dann spätestens unter Unixoiden auftreten


----------

