# Files über Classpath laden



## reibi (14. Aug 2010)

Hi

Wenn ich unbekannt viele Files aus einem Verzeichnis laden will kann ich das ja so machen:


```
File[] myFiles = myDir.listFiles(myFilter);
```

Das funktioniert prima wenn ich den  Pfad kenne.

Wenn ich aber die Files über den Klassenpfad laden muss, da sie sich in einem von Maven gebieldeten Artifakt befinden geht das nicht mehr.

Einzelfiles bei denen der Name bekannt ist, lade ich so:


```
ClassLoader.getSystemResourceAsStream("cpconf/cpconf.properties");
```

blos wie mache ich das bei Dateien wo der Name(und die Anzahl) nicht bekannt ist? 


Gruss

reibsen;-)


----------



## Murray (15. Aug 2010)

Du willst alle Dateien laden, die sich im Classpath befinden?


----------



## reibi (15. Aug 2010)

nee ...nur die Files aus einem bestimten verzeichnis(in dem Fall package) .. dh nicht alle Files aus dem Classpath


----------



## XHelp (15. Aug 2010)

Ist das denn eine jar? Dann kannst du ja mithilfe von ZiFile darüber interrieren.
Vllt wäre für dich interessant: ClassFinder


----------



## reibi (15. Aug 2010)

Ist nicht in jedem file ein jar-file. Erst nach dem builden mit Maven ist es ein Jar-file ... ansonsten liegt das Zeug im Resource-Verzeichnis, welches maven zu einem source-folder für eclipse macht.

Also in jedem Fall in einem richtigen package und man kann ausschliesslich über "ClassLoader.getSystemResourceAsStream" drauf zugreifen. Das bedeutet es muss irgendwie über Reflection gehen.


----------



## Otzelot (15. Aug 2010)

```
BufferedReader is = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("bilder/")));
			
			String line = "";
			while((line = is.readLine())!= null)
				System.out.println(line);
```

Wenn du dir die Ausgabe anguckst werden alle Datein innerhalb dieses Ordner ausgegeben. Diese kannst du speichern und dann irgendwie weiterverarbeiten, wenn du das ganze dynamisch programmierst sollte das kein Problem mit unterschiedlich vielen Dateien sein.

EDIT: Ich weiß allerdings nicht was dein Code macht der ganz oben steht. Eventuell kannst du dort irgendwie den Pfad über den ClassLoader mit reinbringen?


----------



## reibi (15. Aug 2010)

Hi 

das funktioniert nur ungbebunden, zB wenn ichs in meinem Eclipse starte...
Gebunden(in nem JarFile) läuft das nicht mehr.

keine ausgabe, (sprich kein File)
Der Punkt ist, dass es sich nicht mehr um ein Verzeichnis handelt.

Schau
[Java]
        URL url = ClassLoader.getSystemResource("test/test");
        System.out.println(url.toString());
[/Java]


Gibt ungebunden folgende Ausgabe:
file:/C:/Workspaces/WS_X/myPRJ/target/classes/test/test

und gebunden diese:
jar:file:/C:/Workspaces/WS_X/myPRJ/target/z_weg-1.0-SNAPSHOT.jar!/test/test


verstehste?


Gruss und trotzdem danke fürs kopfzerbrechen ;-)


----------



## maki (16. Aug 2010)

Klar geht das 

ClassLoader.getResourceAsStream ist etwas anderes als getSystemResource#getSystemResource, 'ne URL ist doch überflüssig wenn man den Stream bereits hat.


----------



## reibi (16. Aug 2010)

Hi Maki und Otzelot

propiert doch mal das aus, dann seht Ihr das es nicht geht.


```
BufferedReader is = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("java/lang/")));
        
        String line = "";
        while((line = is.readLine())!= null)
            System.out.println(line);
```

Da gibts ne :: java.lang.NullPointerException


Gruss ;-)


----------



## maki (16. Aug 2010)

Du musst schon aufpassen was du da machst.

Es gibt Unterschiede zwischen 

```
ClassLoader.getSystemResourceAsStream
ClassLoader.getResourceAsStream
Class.getResourceAsStream
```
heissen alle ähnliche, und funktionieren alle leicht anders 

NOrmalerweise nimmt man ClassLoader.getResourceAsStream


----------



## reibi (16. Aug 2010)

Hallo maki


probier mal bitte aus:


```
public class App {
    InputStream getIS2(String pack) {
        return this.getClass().getClassLoader().getResourceAsStream(pack);
    } // end getIS2()

    InputStream getIS3(String pack) {
        return this.getClass().getResourceAsStream(pack);
    } // end getIS3()

    public static void main(String[] args) throws Exception {
        String pack = "java/lang/";

        InputStream myIS1 = ClassLoader.getSystemResourceAsStream(pack);
        InputStream myIS2 = (new App()).getIS2(pack);
        InputStream myIS3 = (new App()).getIS3(pack);

        try {
            BufferedReader myBR = new BufferedReader(new InputStreamReader(myIS1));
            String line = "";

            while ((line = myBR.readLine()) != null)
                System.out.println(line);
        } // end try
        catch (Exception e) {
            e.printStackTrace();
        } // end catch

        try {
            BufferedReader myBR = new BufferedReader(new InputStreamReader(myIS2));
            String line = "";

            while ((line = myBR.readLine()) != null)
                System.out.println(line);
        } // end try
        catch (Exception e) {
            e.printStackTrace();
        } // end catch

        try {
            BufferedReader myBR = new BufferedReader(new InputStreamReader(myIS3));
            String line = "";

            while ((line = myBR.readLine()) != null)
                System.out.println(line);
        } // end try
        catch (Exception e) {
            e.printStackTrace();
        } // end catch
    } // end main()
} // end App
```


Bei mir liefern alle 3 Methodiken eine "NullZeigerAusnahme" 

Grüsschen


----------



## maki (16. Aug 2010)

Reibi, was genau willst du denn als Stream laden? 

Muss schon eine Ressource dasein 

Ansosnten, wie gesagt: Die Methoden funktionieren alle leicht anders.

In einem Jar/War/Ear kann man Ressourcen nur als Streams laden, das geht, schon seit Jahren


----------



## reibi (16. Aug 2010)

Also ich will dynamisch (bzw. generisch) an die Inhalte eines Packages rankommen.

sprich ich will das hier:

[Java]
File[] myFiles = myDir.listFiles(myFilter);
[/Java]

mit maven(oder nach maven) machen.

verstehste ;-)


----------



## mvitz (16. Aug 2010)

Das Problem des TOs ist es, dass er x-beliebige Dateien mit unbekannten Namen über den Classpath laden möchte.

Ich habe mich mit der Problematik noch nicht genauer beschäftigt, kann mich aber an viele ähnliche Threads hier erinnern, in der das Ergebnis war, dass dies nicht geht.
Als Ersatzidee wäre es evtl. ein bekanntes File zu erstellen, dass die Pfade/Namen aller anderen Ressourcen enthält, dann könntest du das bekannte File auslesen und anschließend nacheinander jedes der dort referenzierten Files laden.


----------



## reibi (16. Aug 2010)

mvitz hat gesagt.:


> Als Ersatzidee wäre es evtl. ein bekanntes File zu erstellen, dass die Pfade/Namen aller anderen Ressourcen enthält, dann könntest du das bekannte File auslesen und anschließend nacheinander jedes der dort referenzierten Files laden.



Das hab ich mir auch schon überlegt (auch als ErsatzIdee ;-) ) fände das aber nich so doll, da mab Informationen immer doppet hosten muss und sich dadurch auch ein zusätzlichs Fehlerpotential ergibt. 

Aber danke für die Idee ;-)


----------



## maki (16. Aug 2010)

reibi hat gesagt.:


> Also ich will dynamisch (bzw. generisch) an die Inhalte eines Packages rankommen.
> 
> sprich ich will das hier:
> 
> ...


Da bist du auf dem Holzweg, kannst nicht einfach sagen "Gib mir alle klassen von diesem Package", dafür ist getRessourceAsStream nicht da.
getRessourceAsStream gibt dir eine Classpathressource als InputStream zurück 
zB. Property Dateien, XML Dateien, Bilder, etc. pp.


----------



## reibi (16. Aug 2010)

maki hat gesagt.:


> .. dafür ist getRessourceAsStream nicht da.



is mir eigentlich auch klar, hab das auch blos aufgefasst, weil das jemand weiter oben so schrieb.
Folgender Eintrag wird genau erklären wofür ichs brauch.


----------



## reibi (16. Aug 2010)

AT: mvitz und maki

Also stellt Euch mal folgende Problematik vor:

Nur als Beispiel:
Ihr habt einen Sack voll Sprachfiles. Wobei nicht klar ist ob es 2 oder 10 sind. 

Bekannten Dateien wie zB "main.properties" kann man problemlos getResourceAsStream laden

aber bei unbekannten leider nicht. Dafür muss man mir sagen, was der Inhalt des Verzeichnisses ist.

Ohne Classpath laden(was ja bei projekten ohne Maven ganz gut geht) kann man das so machen:


```
File[] myFiles = myDir.listFiles(myFilter);
```

Benutzt man maven, ist man auf einmal gezwungen seine Properties über den Classpath zu laden. das funzt auch gut bei bekannten Dateien ... bei unbekannten aber irgendwie, sehr leider nicht. ;-(


----------



## maki (16. Aug 2010)

reibi, dein Problem hat rein gar nix mit Maven zu tun, man muss Resourcen immer über den CP als Stream laden, sonst funktioniert das nicht in Jars, Wars, EARs, etc. pp.



> Nur als Beispiel:
> Ihr habt einen Sack voll Sprachfiles. Wobei nicht klar ist ob es 2 oder 10 sind.


Dafür nimmt man RessourceBundles, da geht das dann automatisch mit der entsprechen Locale.


----------



## Otzelot (16. Aug 2010)

reibi hat gesagt.:


> Hallo maki
> 
> Bei mir liefern alle 3 Methodiken eine "NullZeigerAusnahme"
> 
> Grüsschen



Alle 3 Methoden funktionieren bei mir auch gebunden in einer .jar. Der Unterschied ist nur, dass man wenigstens den Namen der .jar angeben will bzw. da bei den .class Datein kein Ordner "java/lang" bei mir existiert funktioniert sie natürlich nicht wenn ich sie einfach nur kopiere.

Wenn du die .jar jetzt als Beispiel: test.jar nennst dann ersetzt du deinen String pack = "java/lang"; durch "test.jar" dann werden dir alle Dateien innerhalb der .jar ausgegeben. Zugegeben in einer jar funktioniert das ganze nicht mehr sogut, weil viele komische Sonderzeichen zwischen den Namen kommen, aber diese lassen sich auch rausfiltern.

Ersetz du den String pack durch = ""; dann werden dir alle Datein ausgegebn in der sich die .jar befindet dort kann man dann nach der .jar suchen und den Pfad entsprechend ändern....wenn man es komplett dynamisch machen will.


----------



## KrokoDiehl (16. Aug 2010)

Hallo. Auch wenn es dem TO vielleicht nicht wirklich hilft, aber ich hatte mal ein ähnliches Problem und auch dazu hier im Forum einen Thread gestartet (zu faul zum suchen... ). Bei mir ging es u.A. um den Unterschied der Methoden

```
ClassLoader.getResource()
```
 und 
	
	
	
	





```
ClassLoader.getResource[B]s[/B]()
```
. Letztlich aber ist es harter Fakt, dass man über den ClassLoader nicht mehrere Dateien (InputStreams, URLs) aus einem Verzeichnis im JAR laden/suchen kann. Es gibt Workarounds die über JarFile und ZipFileSet und sowas gehen, aber das ist der Sache auch nicht zuträglich.

Mal von anderen Vorschlägen abgesehen, geht es einfach nicht, via ClassLoader Verzeichnisse auszulesen. 


*edit*
Oh, was ich noch schreiben wollte: Meine Lösung war letztlich so, dass ich über eine andere Quelle an die gewünschten Informationen gekommen bin:
Es ging konkret um Grafiken in einem JAR. Da ich aber bereits über Properties alle verfügbaren Grafikresourcen benannte hatte, war dies meine letztlich meine Datenquelle und ich bekam daraus alle Namen/Pfade im Jar.


----------



## reibi (16. Aug 2010)

KrokoDiehl hat gesagt.:


> .. geht es einfach nicht, via ClassLoader Verzeichnisse auszulesen.



Das ist der Punkt, es geht irgendwie nicht! 

Man kann keine Verzeichnisse über Classloader uslesen, sondern nur Dateien, bei denen der Name bekannt ist.
Bei Verzeichnisen wo der Name bekannt ist, geht das offensichtlich nicht.

Genau das ist auch mein Problem, an dem ich fast verweifele ;-( ... ich sollte mich zum Förster umschulen lassen ..

Gruss und Dank an alle die sich für mich den Koppp zerbrechen ;-)


----------



## reibi (16. Aug 2010)

Otzelot hat gesagt.:


> .. da bei den .class Datein kein Ordner "java/lang" bei mir existiert funktioniert sie natürlich nicht wenn ich sie einfach nur kopiere...



also das package "java/lang" gibts bei jedem 



Otzelot hat gesagt.:


> ... dann werden dir alle Datein ausgegebn in der sich die .jar befindet ...



Es geht aber nicht nur um jar-dateien... es geht um mvn-artifakte, welche zum einen als Eclipse-PRJ vorliegen oder als jar-Datei...

Der Zugriffsmechano MUSS der Gleiche sein! Ansonsten bringts mir nichts.

Wie ich ein jar-File durchsuche, bzw wie ich ein Verzeichnis durchsuche ist mir ja beides klar, blos auf ne unterschiedliche art und Weise. Und genau das ist das Problem. Wenn es nicht gleich ist muss ich jedesmal die Artifakte ändern, je nach dem auf welche Art ich sie benutze ... verstehste? 

Grüssli ;-)


----------

