• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

[Java] relative Pfade in einem jar-Archiv?

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
Hallo,

ich habe ein Programm, das normal als .class-Datei und gut läuft.
es macht nichts anderes als die Datei "Property.txt" mit Werten zu füllen. Ich greife dabei so auf die Datei zu:
Code:
BufferedWriter out = new BufferedWriter(new FileWriter("Property.txt"));

wenn ich alles (die .class-datei und property.txt) in ein jar-archiv verpacke, wird nicht die Datei "Property.txt" im jar-archiv sondern die Datei "Property.txt" im source-ordner editiert. Wieso?
 

Demo

Süssreinette (Aargauer Herrenapfel)
Registriert
02.04.04
Beiträge
411
Ganz im Groben und zum weiterkniffeln. Du musst/kannst dies ueber einen Klassenlader bzw. Stream loesen.
Code:
Class A
{

/*-------------schnipp-------------------*/
void laden()
{
InputStream in = getClass().getResourceAsStream("propertie.txt");
}

/*---------------------------------------*/
}
Du bekommst also Deine Datei als Ressource ueber den sogenannten Klassenlader, deralle Dateien entdeckt, die im Pfad des Klassenladers eingetragen ist. Das gilt zum Beispiel fuer Jar Archive, hier ist alles vom Klassenlader verfuegbar. Reicht der Denkanstoss ?
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Das kommt auf Deinen Klassenpfad an - so, wie Du das angegeben hast, liegt die Datei einfach im Working Directory.

Eine Textdatei aus einem Jar kannst Du sowieso nicht einfach so zurückschreiben.

Ressourcen legt man z.B. in einem eigenen Ordner resources/ ab, wenn Dus gezippt haben willst und schreiben willst, dann muss Du in den saueren Apfel beissen und Dir das Zipfile auspacken, und das neue Entrie hinufügen und wieder wegschreiben. Wie sinnvoll das ist, musst Du selbst entscheiden.

Gruß,

.commander
 

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
@commander: auspacken und wieder einpacken, wäre etwas umständlich, gibt es keine andere möglichkeit?

Demo schrieb:
Ganz im Groben und zum weiterkniffeln. Du musst/kannst dies ueber einen Klassenlader bzw. Stream loesen.
Code:
Class A
{

/*-------------schnipp-------------------*/
void laden()
{
InputStream in = getClass().getResourceAsStream("propertie.txt");
}

/*---------------------------------------*/
}
Du bekommst also Deine Datei als Ressource ueber den sogenannten Klassenlader, deralle Dateien entdeckt, die im Pfad des Klassenladers eingetragen ist. Das gilt zum Beispiel fuer Jar Archive, hier ist alles vom Klassenlader verfuegbar. Reicht der Denkanstoss ?
das habe ich auch schonmal versucht, aber damit kann ich doch keinen OutputStream bekommen, oder?
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Erstmal zum Stream: ein getResource(String name) liefert eine URL, aus der Du dann den Filenamen beziehen kannst und gegebenenfalls ein File erzeugen kannst. ABER: In Deinem Fall wirst Du an der URL schon sehehn, dass das Protokoll zwar file: lautet aber ein '!' im Pfad ist. Alles nach dem '!' liegt in einem Jar.

Und: Nein, soweit ich weiß gibt es keine andere Lösung. Aber Du kannst ja das Propertyfile verschlüsseln, wenns keiner einfach so lesen können soll.

Gruß,

.commander
 

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
das lesen wäre nicht das problem, sondern die plattforumunabhänigkeit. wo soll ich es sonst hinspeichern?
d.h. ich kann auf files in einem jar nur lesend zugreifen?
 

Demo

Süssreinette (Aargauer Herrenapfel)
Registriert
02.04.04
Beiträge
411
Wikinator schrieb:
das lesen wäre nicht das problem, sondern die plattforumunabhänigkeit. wo soll ich es sonst hinspeichern?
d.h. ich kann auf files in einem jar nur lesend zugreifen?

Eine einfache Loesung waere ein Ordner im Home Verzeichnis des Users. Unter Linux/Unix waere zum Beispiel ein versteckter Ordner machbar (.Ordner), unter Windows wuerde man den dann halt sehen.
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Wie gesagt, normalerweise würde ich Resourcen immer in einen getrennten Ordner unterhalb des Programmordners legen - bei Mac wird das dann sowieso unsichtbar, und Winuser sind Chaos gewöhnt. (Schau Dir mal den jar-Bundler in den Developertools an! Schau Dir mal die Struktur an, die dieser erzeugt, da bieten sich einige gute Plätze für den Resourcenordner an.).

Also ungefähr so:

Code:
Programmordner/ 
    - libs/
    - resource/

Wenn Du dem Javaaufruf einfach ein ./resources mit in den Klassenpfad gibst, dann kannst Du in diesem Verzeichniss rumturnen, Files anlegen, löschen - wie Du lustig bist, und kannst trotzdem sicher über den Classloader zugreifen, sodaß Du nicht an festverdrahtete Pfade gebunden bist. Denn wenn Du weißt, daß in Deinem Klassenpfad die Datei meine.properties rumkugeln, dann holst Du Dir die mit dem (übrigens korrekterem als ein getClass() ) Aufruf:

Code:
URL meineUrl = Thread.currentThread().getContextClassLoader().getResource("meine.properties");

File meinFile;

//Absichern: ist vorhanden, ist ein File, und ist nicht in einem JAR!
if(meineUrl != null && meineUrl.getFile() != null && meineUrl.getFile().indexOf("!") == -1)
  meinFile = new File(meineUrl.getFile());

So, nun kannst Du auf dem File rumhühnern. Wenn Du später die Ordnerstruktur ändern willst, musst Du nur diese anderen Ordner in den Klassenpfad aufnehmen, aber am Code nichts ändern.

btw: getResource() verlangt einen relativen Pfad, nicht nur den Namen (also: properties/meine.properties) falls das gesuchte File da liegen würde: resources/properties/meine.properties und resources/ im Klassenpfad ist)

Gruß,

.commander
 
Zuletzt bearbeitet:

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
hm, ich bin irgendwie verwirrt.
commander schrieb:
Also ungefähr so:

Code:
Programmordner/ 
    - libs/
    - resource/
ist der Programmordner ein jar-archiv oder wo ist das jar-archiv? ansich kann es auch in das unterverzeichnis "resources", nur ist es dann doch immer noch in einem jar-archiv.
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Ok, nochmal etwas ausführlicher. Es gibt sicher verschiedene Wege, eine Javaapplikation zu strukturieren, ich mache das aber meistens so:

Du nimmst einen übergeordneten Ordner an, beim Entwickeln einfach den Ordner des Projekts, bei einem fertigen Programm einfach einen Ordner MeineApplikation.app/ z.B.

Darunter hast Du ein libs/ Verzeichnis, in das alle jars, egal ob extern oder Deine liegen. In den jars sind NUR Klassen und _unveränderliche_ Resourcen wie Übersetzungen und Bilder usw, obwohl ich die immer getrennt in ein zip legen würde. Diese Files nimmst Du _einzeln_ in deinen Klassenpfad mit auf.

Ressourcen wie dein Propertyfile, in die also zur Laufzeit geschrieben werden soll, lege ich in ein Verzeichnis resources/ , das dann ebenfalls in den Klassenpfad kommt, also z.B. ein java -cp ./resources/:./lib/meins.jar:./lib/externes.jar. Du nimmst als den _Ordner_ resources/ in den Klassenpfad auf!

Wenn Du nun in das resources/ Verzeichnis dein Propertyfile ablegst (wegen mir anfangs leer), dann kannst Du wie beschrieben über den Classloader zugreifen. Das ist übrigens die sichereste und standardmässigste Vorgehensweise.

Wenn Du den jar-Bundler verwendest, muss Du den ganzen Summs eben entsprechend dort in den Klassenpfad aufnehmen.

Das bauen von solchen Applikation erledigt bei mir idR die Scriptsprache ANT, solltest Dir irgendwann mal anschauen, wenn Dir das jaren und zippen und rumkopieren zum Hals raushängt. ;)

Gruß,

.commander
 
Zuletzt bearbeitet:

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
danke für die ausführliche Arbeit, auf Dauer wäre ant wohl wirklich besser o_O
 

commander

Baldwins roter Pepping
Unvergessen
Registriert
25.02.04
Beiträge
3.206
Äh, und nun?

Bedeuted Deine knappe Antwort, daß Du verstanden hast, was ich Dir erklären wollte? Oder daß es Dir zu dumm war, nochmals zu fragen?

Falls zweiteres: Frag einfach, ich helfe gerne. :-D

Gruß,

.commander
 

Wikinator

Adams Parmäne
Registriert
21.08.04
Beiträge
1.297
commander schrieb:
Äh, und nun?

Bedeuted Deine knappe Antwort, daß Du verstanden hast, was ich Dir erklären wollte? Oder daß es Dir zu dumm war, nochmals zu fragen?

Falls zweiteres: Frag einfach, ich helfe gerne. :-D

Gruß,

.commander

es heißt, ich hab's soweit verstanden und bin am umsetzen. :-D