Ressourcen dynamisch zur Laufzeit laden

hdi

Top Contributor
Hey,

die Frage wäre: Kann ich die Dateien in einem package zur Laufzeit ermitteln? Also nicht Dateien in einem externen Jar, sondern in einem Package innerhalb meines Projekts?

Hintergrund: Ich habe ein /icons package, das all meine GUI-Icons enthält. Im Moment lade ich die alle einzeln per

Java:
ImageIO.read(MyIcons.class.getResource("/icons/test.png"));

Natürlich hab ich mir das mit ner VarArg-Methode und ner Schleife schon so angenehm wie möglich gemacht, trotzdem muss ich den Methodenaufruf jedesmal anpassen, wann immer ich ein Bild lösche/hinzufüge/umbenenne.

Das ist grad ziemlich nervig weil ich recht viele Icons hab und ich spiel grad etwas mit der Optik rum und kuck mir die verschiedensten Icons an. Schön wäre es wenn ich einfach nur das package an sich mit neuen Icons füttere und mein Programm beim Start einfach alle lädt und mir in ne Map legt (<Dateiname>, <geladenes Icon>)

Möglich? Danke!
 

Antoras

Top Contributor
Was hindert dich daran das Jar-Archiv einfach zu durchsuchen und die benötigten Dateien zu laden? Ich hab da mal was zusammen gebastelt, hab aber keine Ahnung ob man das nicht auch ein bisschen einfacher erreichen kann:
Java:
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.imageio.ImageIO;


public class Main {

	public static void main(final String... args) throws IOException {
		final Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();
		
		for (final JarEntry e : Collections.list(new JarFile(jarName()).entries())) {
			if (isIcon(e.getName())) {
				final String fileName = "/" + e.getName();
				map.put(fileName, ImageIO.read(Main.class.getResource(fileName)));
			}
		}
		
		for (final Map.Entry<String, BufferedImage> me : map.entrySet()) {
			System.out.println(me.getKey() + ", <a file>");
		}
	}
	
	static boolean isIcon(final String str) {
		final String[] s = str.split("/");
		return str.contains("icons/") && s[s.length - 1].endsWith(".png");
	}
	
	static String jarName() {
		final String s[] = Main.class.getProtectionDomain().getCodeSource().getLocation().toString().split("/");
		return s[s.length - 1];
	}
}
Das hat mir alle png-Dateien im Verzeichnis "icons" geladen. Das Problem bleibt halt, dass du vor der Kompilierung wissen musst welches Icon du welcher Komponente zuordnest. Am Komfortabelsten wäre es wohl wenn die Bild-Dateien einen Identifier der Komponente im Namen beinhalten würden auf die sie platziert werden sollen, dann müsstest du diesen nur extrahieren und die Datei der Komponente zuordnen.
 
Zuletzt bearbeitet:

hdi

Top Contributor
Danke schonmal, das sieht ja genau nach dem aus was ich suche. Aber es gibt leider ein Problem: Beim Konstruktor-Aufruf von von JarFile fliegt folgende Exception:

Java:
java.io.FileNotFoundException: bin (Access is denied)
	at java.util.zip.ZipFile.open(Native Method)
	at java.util.zip.ZipFile.<init>(Unknown Source)
	at java.util.jar.JarFile.<init>(Unknown Source)
	at java.util.jar.JarFile.<init>(Unknown Source)
	at gui.IconPool.loadIcons(IconPool.java:32)
	at runtime.Main$1.run(Main.java:29)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Ich hab's auch schon statt dem Ergebnis von jarName() = bin, mit dem vollen Pfad versucht der von
Code:
MyClass.class.getProtectionDomain().getCodeSource().getLocation().toString()
zurückgegeben wird. Aber auch hier fliegt eine FileNotFoundException, mit der Bemerkung

(The filename, directory name, or volume label syntax is incorrect)
 

Antoras

Top Contributor
Was für einen Pfad gibt denn
Code:
MyClass.class.getProtectionDomain().getCodeSource().getLocation().toString()
zurück und unter welchem Pfad ist das Jar-Archive gespeichert?

Hab den obigen Code angepasst, jetzt sieht er ein bisschen übersichtlicher aus.
 

hdi

Top Contributor
unter welchem Pfad ist das Jar-Archive gespeichert?
Ach ich glaube wir reden aneinander vorbei. Ich habe kein Jar-Archiv. Ich dachte er kann das zur Laufzeit aus dem eigenen Projekt ziehen. Wenn ich alle Bilder in ein jar legen müsste wäre der Umstand ja wieder so groß. Jedesmal ein neues Jar erstellen wenn ich was ändere.

Nein, ich möchte dass er die Dateien innerhalb eines packages in meinem Projekt lädt, nicht aus irgendnem jar...
 

Antoras

Top Contributor
Wenn du kein Jar-Archiv hast, dann kannst du ganz einfach über die Klasse
Code:
File
auf die Dateien zugreifen, z.B.
Code:
new File("bin/icons").listFiles()
. Der Rest ist dann praktisch identisch zu obigen Code, nur dass die Schleife eben über die Files iteriert und nicht über die JarFiles.
 

hdi

Top Contributor
Oh, daran hab ich gar nicht gedacht. Aber ich steh grad etwas auf dem Schlauch und - ich geb's zu - habe gerade keinen Nerv (weil dafür eig. keine Zeit) dafür.. Was für einen Pfad muss ich denn jetzt genau nehmen, damit das später als JAR auch noch funzt?

D.h. die Frage ist: Wie bekomme ich den Pfad dieses Ordners innerhalb des JARs zur Ausführungszeit?

Danke!
 

XHelp

Top Contributor
Zuerst JAR, dann doch kein JAR, dann doch plötzlich JAR... du solltest dich mal entscheiden was du willst...
Innerhalb einer Jar kannst du nicht mit File-Objekten arbeiten.
 

hdi

Top Contributor
Zuerst JAR, dann doch kein JAR, dann doch plötzlich JAR... du solltest dich mal entscheiden was du willst...
Naja, ich habe kein Archiv für meine Bilder, die liegen nur in einem Package innerhalb meines Projekts. Deshalb sagte ich kein Jar. Aber natürlich soll das ganze nicht nur während der Entwicklung funktionieren, wenn ich es über Eclipse compile und starte. Sondern auch später wenn das Programm - als JAR! - ausgeliefert wird.
Ich weiß dass es da halt einen Unterschied macht bei Pfadangaben, ob man nun einen Pfad auf der Platte angibt oder einen relativen Pfad innerhalb des Projektes, darauf zielte meine Frage ab.
 

XHelp

Top Contributor
Ich verstehe generell nicht, was es dir bringen soll. Es gibt z.B. ein Bild
Code:
add.png
. Dieses Bild lädst du irgendwo und verwendest es irgendwo. Dafür musst du wissen, dass das Bild
Code:
add.png
heißt. Selbst wenn du das Bild ersetzt, ist es doch dem Programm egal was letztendlich geladen wird.
 

hdi

Top Contributor
Okay also: Ich hab mir für den leichteren Zugriff auf meine Icons eine Klasse "IconPool" gemacht, die in einer Map alle Bilder enthält - und die werden alle beim Programmstart geladen. Diese Bilder hol ich mir an den jeweiligen Stellen im Programm per
Code:
getIcon(String)
raus.

Dass ich diesen Methodenaufruf dann natürlich an diesen Stellen ändern muss, wenn ich Bilder umbennene/hinzufüge/lösche ist klar, darum geht's auch nicht. Es geht darum dass ich zusätzlich immer in der IconPool-Klasse rumpfuschen muss, weil ich dort eben im Moment alle Bilder einzeln lade, und da auch die Dateinamen angeben muss, siehe Aufruf von "loadIcons()":
Java:
public class IconPool {

	private static final Map<String, ImageIcon> icons = new HashMap<String, ImageIcon>();

	public static void populate() throws IOException {
		loadIcons("bla.png", "blub.png"); // und noch hunderte andere...
	}

	private static void loadIcons(String... names) throws IOException {
		for (String name : names) {
			icons.put(name, new ImageIcon(ImageIO.read(IconPool.class.getResource("/icons" + name))));
		}
	}

}

Was ich will ist dass ich da einfach eine Methode habe die mir alle Bilder aus dem package automatisch ausliest, ohne dass ich alle Bildernamen einzeln angeben muss. So müsste ich dann wirklich nur noch an den Stellen im Programm etwas ändern, wo ich mir ein Bild aus der Map ziehe, aber an der IconPool Klasse selber nichts mehr.

Die Bilder liegen nun halt NICHT in nem Jar, weil das wäre ja bei all den Änderungen auch sehr umständlich immer ein neues JAR zu generieren, da kann ich gleich die Namen im Methodenaufruf oben anpassen. Aber: Ich kann jetzt nicht mit absoluten Pfadangaben bei Files daherkommen, da er die bilder dann im Moment bei mir finden würde, aber wenn ich das Projekt als JAR exportier und dir als User schicke, dann findet er sie nicht mehr, weil sie bei dir nicht auf der Platte liegen sondern innerhalb des JARs.

Ist jetzt etwas klarer worum es mir geht? Er soll einfach alle Icons aus dem package laden, ist mir wurscht wie die heißen, beim Zugriff auf die Map weiss ich das dann schon, ich seh sie ja in meinem Package, aber ich will die nicht immer hier in dieser Klasse angeben müssen beim Namen...
 
Zuletzt bearbeitet:
G

Gastredner

Gast
Mach es doch folgendermaßen:
Zunächst lädt IconPool mit dem Code von Antoras alle Icons aus dem Jar-internen Ordner. Anschließend wird überprüft, ob es im Arbeitsverzeichnis einen Ordner "icons" gibt. Sollte dem so sein, so lädst du alle in diesem abgelegten Bilddateien und steckst sie in dieselbe Map wie die zuvor aus dem Jar geladenen. So hast du ein jederzeit verfügbares Icon-Set innerhalb deines Jars und kannst über den Ordner diese schnell austauschen.
Innerhalb deines Eclipse-Projekts deaktivierst du das Laden der Icons aus dem Jar (da dies nicht funktioniert) und lädst die Icons stattdessen ausschließlich aus einem Ordner icons, welcher direkt in deinem Projektverzeichnis liegt (einfach eine Kopie des Ordners innerhalb deiner Packagestruktur).
 

Antoras

Top Contributor
Innerhalb deines Eclipse-Projekts deaktivierst du das Laden der Icons aus dem Jar (da dies nicht funktioniert) und lädst die Icons stattdessen ausschließlich aus einem Ordner icons, welcher direkt in deinem Projektverzeichnis liegt (einfach eine Kopie des Ordners innerhalb deiner Packagestruktur).
Alternativ kannst du auch einfach eine Abfrage einbauen, die prüft ob der Code von der IDE oder von einem Jar-Archiv ausgeführt wird. Dazu würde ich einfach den Ausführungspfad der Main-Klasse ermitteln und dann prüfen ob er auf
Code:
.jar
endet. Das hätte den Vorteil, dass du nicht die ganze Zeit am Code rumwerkeln musst.
 

hdi

Top Contributor
Also ich bin mir nicht sicher ob ich das richtig verstanden habe. Ihr meint:

Java:
try{
     // Antoras Code, d.h. mit Jar - wird später bei der Auslieferung funktionieren
}
catch(FileNotFoundException e){
     // denn die fliegt ja bei mir im Moment. Nur weil ich das Programm im Moment eben nicht über ne JAR starte?
     // Hier jetzt das ganze Spiel nur mit File statt Jar?
}

Ist das so? Wenn nicht hab ich die letzten 2 Beiträge leider nicht ganz verstanden.

Ich weiß außerdem nicht welchen konkreten Pfad ich verwenden soll im dem Fall dass ich nicht mir der JAR sondern mit File arbeite. Ich kenn mich leider mit diesen ganzen class-bezogenen Dingen aus der API nicht so aus. Also den Pfad zur Jar hat ja Antora gepostet, aber wie sieht der für File aus.

new File(???)

Meine Struktur:
IconPool liegt in package gui
Bilder liegen in package gui.icons

Danke!
 
G

Gastredner

Gast
[c]new File("./icons");[/c] für den Ordner icons, würde ich mal sagen. Der Punkt sollte sogar unnötig sein, da File-Objekte bei fehlender Laufwerksangabe bzw. ohne Filesystem-Root mit relativen Pfaden arbeiten (relativ zum aktuellen Arbeitsverzeichnis). Ansonsten gäbe es noch die sichere Variante [c]new File(System.getProperty("user.dir") + "/icons");[/c]

Und nein, so hatte zumindest ich mir das nicht vorgestellt. Du könntest z. B. zwei Methoden schreiben: [c]loadFromArchive()[/c] und [c]loadFromDirectory()[/c]. Erstere würde versuchen, die Icons mit der von Antoras aufgezeigten Methode aus dem Jar zu laden. Entweder kommentierst du den Aufruf dieser Methode aus, wenn du in Eclipse arbeitest, oder du schreibst sie so, dass sie einfach abbricht, sollte dein Code nicht in einem .jar liegen. Die zweite Methode sucht nach dem externen Ordner und lädt, sofern er existiert, die dortigen Icons, die dann u. U. die zuvor geladenen auch überschreiben.
Wenn du im Eclipse-Projekt dann noch eine Kopie deines icon-packages direkt im Projektordner selbst erstellst (damit [c]loadFromDirectory[/c] diese auslesen kann), dann sollte es kein Problem mehr sein, Icons schnell mal auszutauschen.
 
Zuletzt bearbeitet von einem Moderator:

Runtime

Top Contributor
Eine Alternative wäre eine Datei, in der alle Dateinamen gespeichert sind. Die Dateinamen kannst du von diesem Programm in die Datei schreiben lassen. (Ungetestet!)
Java:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;

public class Main {

    public static void main(String[] args) throws FileNotFoundException {
        File dir = new File(args[0]);
        File[] files = dir.listFiles();
        File file = new File(dir, "output.txt");
        PrintStream out = new PrintStream(file);
        for(File f : files) {
            if(f.isFile()) {
                out.println(f.getName());
            }
        }
        out.close();
    }

}
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Mehrere Ressourcen in einem package ablegen Allgemeine Java-Themen 1
S Pfad zu Ressourcen Allgemeine Java-Themen 17
BRoll Ladestatus Ressourcen betrachten Allgemeine Java-Themen 5
P Textdatei aus Ressourcen laden. Allgemeine Java-Themen 8
D Ressourcen(config) laden Allgemeine Java-Themen 11
C Threads Verbraucht eine Zeitabfrage viele Rechen-Ressourcen? Allgemeine Java-Themen 8
Kr0e Verbraucht ein schlafender Thread Ressourcen ? Allgemeine Java-Themen 8
M Wie externe System-Ressourcen zwangsweise freigeben Allgemeine Java-Themen 2
S Spiel - Ressourcen Allgemeine Java-Themen 10
G emf.ressourcen Allgemeine Java-Themen 7
F [JAR] Namenskonventionen für Ressourcen Allgemeine Java-Themen 2
D Alle Ressourcen auslesen Allgemeine Java-Themen 4
L Ressourcen Java Applikation Allgemeine Java-Themen 4
K Frage zur Deklaration von Variablen und deren Ressourcen Allgemeine Java-Themen 17
G Mit Klassenlader Sound Ressourcen laden Allgemeine Java-Themen 10
G Java-Webstart-Ressourcen Allgemeine Java-Themen 2
P Woher weiß ein Programm wo seine Ressourcen sind? Allgemeine Java-Themen 4
berserkerdq2 Jemand einen Tipp wie man ein Javafx-Hintergrund "dynamisch" macht Allgemeine Java-Themen 3
E RMI FWH: RMI- Wie erstelle ich stubs dynamisch, bzw. unterdrücke eine Statisch-Warnung? Allgemeine Java-Themen 0
S Maven Jars dynamisch laden / Plugin-Struktur erstellen Allgemeine Java-Themen 14
T Statisch und dynamisch Allgemeine Java-Themen 1
MiMa Variableninhalte dynamisch abfragen Allgemeine Java-Themen 12
D Methode dynamisch aufrufen Allgemeine Java-Themen 2
S Externe Eclipse Projekte dynamisch einbinden Allgemeine Java-Themen 3
Thallius Externe .jar dynamisch einbinden Allgemeine Java-Themen 5
C Erste Schritte Baumstruktur (dynamisch) Allgemeine Java-Themen 9
F JTree: Nodes dynamisch anlegen via LinkedHashMap Allgemeine Java-Themen 2
B Reflection, invoke dynamisch befüllen Allgemeine Java-Themen 3
M Klassen Klasse Dynamisch laden und Konstruktor aufrufen Allgemeine Java-Themen 1
J rxtxserial.dll für 32 oder 64bit dynamisch einbinden Allgemeine Java-Themen 9
F Dynamisch ein Objekt einer bestimmten Subklasse erstellen Allgemeine Java-Themen 7
W Dateinamen dynamisch Parsen Allgemeine Java-Themen 12
T Classpath Klassen dynamisch erstellen Allgemeine Java-Themen 4
F Schlüsselworte Einstellungen dynamisch deserialisieren Allgemeine Java-Themen 5
S LaTeX Code in dynamisch erzeugten PDF's Allgemeine Java-Themen 8
X Dynamisch Konstruktor aufrufen Allgemeine Java-Themen 12
A Klassen dynamisch aus jar-datei laden Allgemeine Java-Themen 5
J instanceof vermeiden und stattdessen dynamisch binden Allgemeine Java-Themen 6
M Konstruktoraufruf dynamisch auswerten und SQL bauen Allgemeine Java-Themen 10
E Variable dynamisch ausgeben Allgemeine Java-Themen 5
Tandibur pattern dynamisch vorkompilieren Allgemeine Java-Themen 9
T Objekt dynamisch neu erstellen/ austauschen Allgemeine Java-Themen 9
T Dynamisch getypte Klasseninstanz? Allgemeine Java-Themen 6
H getText(); bei dynamisch generierten JTextFiled Allgemeine Java-Themen 2
F Wie erfahre ich dynamisch den namen eines aktuellen Objektes Allgemeine Java-Themen 2
S Asymmetrisches Array dynamisch erzeugen Allgemeine Java-Themen 4
T Objekte dynamisch über eine Methode erzeugen Allgemeine Java-Themen 10
R Object Dynamisch erzeugen (Reflection API) Allgemeine Java-Themen 22
P RTF dynamisch machen (IText, Swing) Allgemeine Java-Themen 4
B Listener dynamisch setzen Allgemeine Java-Themen 6
P Klasse Dynamisch laden und zurückgeben Allgemeine Java-Themen 17
P Array Dynamisch vergrößern Allgemeine Java-Themen 7
B objekt einer klasse dynamisch erzeugen Allgemeine Java-Themen 6
G Objekt dynamisch erstellen und Inhalte kopieren Allgemeine Java-Themen 6
C Dynamisch Objekte unterschiedlicher Typen erzeugen Allgemeine Java-Themen 6
D Klassen dynamisch laden Allgemeine Java-Themen 5
E Arrays -> dynamisch Allgemeine Java-Themen 21
K Methoden dynamisch erstellen Allgemeine Java-Themen 12
P Dynamisch casten - möglich? wie? Allgemeine Java-Themen 5
T Klassen dynamisch ausführen Allgemeine Java-Themen 3
N Graphische Oberfläche dynamisch erweitern möglich? Allgemeine Java-Themen 4
B Absolute Paf einer Klasse in dieser dynamisch auslesen? Allgemeine Java-Themen 5
K Klasse dynamisch casten Allgemeine Java-Themen 14
Reeny Dynamisch Klassen kompilieren Allgemeine Java-Themen 5
G JDO Dynamisch ? Allgemeine Java-Themen 2
H Objekte m. versch. Interf. dynamisch erzeugen Allgemeine Java-Themen 11
E Klasse dynamisch über main-Methode aufrufen Allgemeine Java-Themen 9
D Strings dynamisch füllen Allgemeine Java-Themen 5
A Dynamisch Attribute hinzufügen Allgemeine Java-Themen 3
S Build-Zeitpunt (Datum und Uhrzeit) irgendwie während der Laufzeit zugänglich machen..? Allgemeine Java-Themen 4
M Laufzeit des Prim Algorithmus Allgemeine Java-Themen 3
M Laufzeit LinkedList Allgemeine Java-Themen 9
M verbesserte Laufzeit bei LinkedList Allgemeine Java-Themen 7
K Verbesserung der Laufzeit beim Sortieren von Einwohnern nach ihrem Geburtsjahr Allgemeine Java-Themen 0
H was ist den dieses zur Kompilierzeit und zur Laufzeit in Java? Allgemeine Java-Themen 3
L Classpath Zur Laufzeit bestimmte Klassen in Classloader hinzufügen? Allgemeine Java-Themen 4
L Compiler-Fehler Google Guice Module zur Laufzeit zusammenstellen und binden Allgemeine Java-Themen 4
J Jasper Reports - Subreport zur Laufzeit ändern Allgemeine Java-Themen 6
O jar und EXE Dateien, Pfade zur Laufzeit Allgemeine Java-Themen 1
T Externe Java Klasen zur Laufzeit einbinden Allgemeine Java-Themen 10
X Collections Gibt es eine Klasse welche die Vorteile von List und HashMap vereint, aber konstante Laufzeit (O(1)) hat in Java? Allgemeine Java-Themen 4
D Boolean von ein anderem Java Programm während der Laufzeit ändern Allgemeine Java-Themen 23
N Generic Type einer Generischen Klasse während der Laufzeit bekommen Allgemeine Java-Themen 2
J .java-Dateitext Compile zur Laufzeit ohne File Allgemeine Java-Themen 15
kodela Daten während Laufzeit zugriffsbereit Allgemeine Java-Themen 15
Neumi5694 Interpreter-Fehler final Eigenschaft während Laufzeit geändert Allgemeine Java-Themen 2
A Java Klasse auf Tomcat während der Laufzeit austauschen Allgemeine Java-Themen 1
M Sinn von Kompilierung zur Laufzeit Allgemeine Java-Themen 3
T Java Class Intrumentation mit Annotations in Laufzeit Allgemeine Java-Themen 1
S Byte Array welches in Laufzeit aufgelöst wird // Objekt Array Allgemeine Java-Themen 3
T Dateien zur Laufzeit in Java-Programm packen? Allgemeine Java-Themen 3
S Laufzeit Primzahlgenerator Allgemeine Java-Themen 18
S Zur Laufzeit Klasse mit einer anzahl von X Objekten erstellen Allgemeine Java-Themen 5
F Classpath Programmteile zur Laufzeit nachladen Allgemeine Java-Themen 6
D Variablen zur Laufzeit global speichern (Registry Pattern?) Allgemeine Java-Themen 6
H ResourceBundle während Laufzeit bearbeiten Allgemeine Java-Themen 3
J Input/Output Jar-Datei zur Laufzeit erweitern Allgemeine Java-Themen 13
P Generic zur Laufzeit Allgemeine Java-Themen 4
A ar während der Laufzeit überschreiben Allgemeine Java-Themen 20
X MergeSort Laufzeit Problem Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben