Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Bin blutiger Java-Anfänger und habe folgenden Code vorliegen:
Java:
//.........
public static void main(String args[]) {
String warning = "\nWarnung: Gleiche Parameter verwendet!\n";
Properties transferPrp = new Properties();
switch (args.length) {
case 0: // es werden keine Parameter an Main übergeben, also soll er Parameter aus Transfer.properties laden
try {
transferPrp.load(new FileInputStream("prp/Transfer.properties"));
}
catch (java.io.IOException e) {
System.out.println("Properties-Datei nicht gefunden: " + e);
};
String srcDir = transferPrp.getProperty("SrcDir"); // Quelle
String destDir = transferPrp.getProperty("DestDir"); // Ziel
//..........
Der Inhalt meiner Properties-Datei besteht aus 2 Zeilen:
SrcDir=D:\Test
DestDir=D:\Test2
Problem: Scheinbar erkennt die Falluntersuchung die Parameter nicht richtig, denn obwohl sie unterschiedlich lauten sagt das Programm ich würde identische Parameter für srcDir und destDir verwenden.
Wie müssen die Parameter korrekterweise in der Properties-Datei angegeben werden?
Vllt. irre ich mich, aber kann es sein dass der Backslash escaped werden muss?
SrcDir=D:\\Test
DestDir=D:\\Test2
@Edit: Nein ich irre mich nicht! Properties (Java 2 Platform SE 5.0)
mhm, also imo sieht das korrekt aus.
was meinst du mit: "denn obwohl sie unterschiedlich lauten sagt das Programm ich würde identische Parameter für srcDir und destDir verwenden."
Das Ganze ist eine Übung aus nem Java Buch und sollte eigentlich funzen.
Hier der komplette Block:
Java:
public class TransferApp {
public TransferApp(String srcDir, String destDir) {
Thread t = new CopyThread("Transfer wartet ...", srcDir, destDir);
Runtime.getRuntime().addShutdownHook(t);
do {
System.out.print(".");
try {
Thread.sleep(1);
}
catch (InterruptedException ie) {
Runtime.getRuntime().halt(1);
}
}
while (true);
}
private static void helpAndTerminate() {
System.out.println("Verwenden Sie bitte zwei unterschiedliche Parameter");
System.out.println("\tTransfer <Quelle> <Ziel>");
System.out.println("oder folgende Properties-Datei:");
System.out.println("\t<Transfer-Verzeichnis>/prp/transfer.properties");
System.out.println("mit folgenden Eintr\u00e4gen:");
System.out.println("\tSrcDir <Quelle>");
System.out.println("\tDestDir <Ziel>");
System.exit(1);
}
public static void main(String args[]) {
String warning = "\nWarnung: Gleiche Parameter verwendet!\n";
Properties transferPrp = new Properties();
switch (args.length) {
case 0: // ................... Fall 1: Keine Parameter => Properties laden
try {
transferPrp.load(new FileInputStream("prp/Transfer.properties"));
}
catch (java.io.IOException e) { // ...... Fall 1.1: Datei nicht gefunden
System.out.println("Properties-Datei nicht gefunden: " + e);
helpAndTerminate();
};
String srcDir = transferPrp.getProperty("SrcDir"); // Quelle
String destDir = transferPrp.getProperty("DestDir"); // Ziel
if (srcDir.equals(destDir)) {
System.err.println(warning);
helpAndTerminate();
}
else { // ..................................... Fall 1.3: Quelle != Ziel
new TransferApp(srcDir, destDir);
}
break;
Die Datei läd er, da ich keine "Properties-Datei nicht gefunden: " -Meldung erhalte.
Er spuckt mir stattdessen System.err.println(warning) aus mit der Meldung "Gleiche Parameter verwendet" (siehe den String weiter oben). Daraus schließe ich, dass er die Parameter aus der Datei nicht richtig einliest, sonst würden die doch nicht equal sein?!
Vielleicht weiß ja wer Rat. Ansonsten gehe ich direkt an den Autor .
Das Programm enthält keine Fehler... aber offensichtlich deine Properties-Datei. WG.: Der Backslash ist ein Sonderzeichen und muss deswegen escaped werden. Bei aufmerksamen Weiterlesen meines Links erfährt man im übrigen, dass selbiges auch für den Doppelpunkt gilt. Deswegen nehme ich mal stark an, das Src- und DestDir equal sind, weil beide leer.
Das Programm enthält keine Fehler... aber offensichtlich deine Properties-Datei. WG.: Der Backslash ist ein Sonderzeichen und muss deswegen escaped werden.
aber hier wird doch schon das key - value durch das erste vorkommen(hier durch das = ) getrennt, daher ist klar, dass der : zum value gehört, daher sollten meine rmeinung nach die strings eben nicht leer sein, oder ?
Bei mir funzt es...
@eRaaa: Tja... "Hätte klar sein müssen...", war es aber nicht. Nun fragen wir uns, als was [c]=D[/c] wohl von Properties interpretiert wird... vllt. als Smiley? :lol:
Hey maki,
Da es ne Übungsaufgabe aus nem Buch ist, ist dein Einwand für mich erstmal nicht entscheidend. Ich muss den Kram ja erstmal grundsätzlich auf die Kette kriegen .
Bist du sicher, dass er überhaupt bis zu dem Vergleich kommt und nicht schon in Zeile 38 rausfliegt? (Die gleiche Fehlermeldung für zwei verschiedene Fehler ist blöd ..)
Er folgt dem if-Block ab Zeile 45. Dort fliegt er dann raus.
Die Datei findet er, sonst würde er ja die Meldung System.out.println("Properties-Datei nicht gefunden: " + e); bringen.
Es stehen nur die beiden Zeilen drinnen.
Nix anderes.
Müssen die beiden Zeilen in der Properties-Datei noch irgendwie als Property explizit gekennzeichnet werden?
Ergibt irgendwie keinen Sinn. Was sein könnte, dass er die Datei nicht findet, aber dann würde er ne Exception schmeißen ... poste mal deine gesamte Klasse.
Fehler gefunden. War mal wieder ein Ding aus dem Tollhaus .
Ich hatte die Java Dateien des Programms nicht über den src-Ordner in Eclipse hinein geladen, sondern eine Ebene tiefer über den Ordner "net" in src (also quasi der erste Teil vom Paket-Pfad). In diesem Ordner net gab es rein zufällig auch einen Unterordner prp mit einer Properties Datei transfer.properties. Hier waren die Einträge SrcDir und DestDir natürlich noch nicht von mir belegt worden. Sehr ärgerlich.
Zum Glück habe ich gerade noch ein weiteres Problem. Muss euch doch beschäftigen .
Im oberen Teil des Proggys wird ja ein Shutdownhook gesetzt. Wie kann ich diesen denn auslösen? Wenn ich das Prog starte, dann initialisiert er den hook, aber wenn ich den run in eclipse wieder beende, dann führt das Prog wider Erwarten nicht die Methode CopyThread aus, die ja eigentlich via hook auf ihre Ausführung wartet?!
Anbei noch die Methode CopyThread:
Java:
class CopyThread extends Thread {
private String srcDir;
private String destDir;
/**
* Erster Konstruktor
* @param message Meldung fuer die Konsolenausgabe
* @param srcDir Quelle
* @param destDir Ziel
*/
public CopyThread(String message, String srcDir, String destDir) {
this.srcDir = srcDir;
this.destDir = destDir;
System.out.println(message); // Meldung auf der Konsole
}
/**
* Zweiter Konstruktor
* @param srcDir Quelle
* @param destDir Ziel
*/
public CopyThread(String srcDir, String destDir) {
this.srcDir = srcDir;
this.destDir = destDir;
}
/**
* Methode run stoesst den Kopiervorgang an
*/
public void run() {
System.out.println("\nKopiere von " + srcDir + " nach " + destDir);
//......
Wenn du in Eclipse den Stopp-Button verwendest, ist das wie alswenn du in Windows im Taskmanager "Prozess beenden" verwendest. Die JVM wird abgebrochen ohne das ShutdownHooks ausgeführt werden. Startest du die Klasse hingegen in einer Konsole, wird auch der Hook ausgelöst, sobald die Main-Methode fertig ist. Nebenbei... Irgendwie fehlt da in Eclipse (meinetwegen auch in anderen IDEs) die Möglichkeit JVMs normal zu beenden.
Irgendwie muss das aber doch auch aus eclipse heraus testbar sein?
Mal was anderes:
Wenn ich es über die Konsole testen will gehe ich das Verzeichnis der *.class Datei und hacke folgendes ein:
java TransferApp.class (Das .class kann ich auch weglassen).
Sollte so funzen, oder?
Bei mir gehts nur irgendwie nicht. Hatte das Theater schonmal. Da stimmt irgendwie der Pfad zum JDK nicht, denn ich erhalte immer classNotFound oder Unknown Source - Fehler.
Hatte mal versucht das Ganze zu richten, hat aber irgendwie nicht geklappt.
Muss man das JDK korrekt in der Systemvariablen %classpath% eintragen, oder wo?
Ich weis nicht genau, aber seit Java1.2 genügt es, das korrekte [c]JAVA_HOME[/c]-Verzeichnis als Umgebungsvariable zu setzen und [c]%JAVA_HOME%/bin[/c] dem Pfad hinzuzufügen. Den Klassenpfad muss man nur ändern, wenn sich ausserhalb des aktuellen Verzeichnisses sowie ausserhalb von [c]%JAVA_HOME%/lib[/c] und [c]%JAVA_HOME%/lib/ext[/c] noch benötigte Bibliotheken befinden. Dass ".class" kann nicht nur weggelassen werden, afaik muss es sogar weggelassen werden.
...und nein, es gibt keine Möglichkeit in Eclipse ShutDownHooks vernünftig zu testen, bis auf die, die Main-Methode normal zu beenden und Breakpoints an zu überwachenden Stellen zu platzieren.
Danke für den Hinweis mit der JAVA_HOME Benutzervariablen.
Prinzipiell ist das genau das, was ich bereits versucht hatte, nur hatte ich der %PATH% Systemvariablen den kompletten Pfad zum JDK zugewiesen.
Leider funktioniert es auch diesmal nicht .
So langsam verzweifel ich, weil ich nix in der Konsole ausführen kann.
Er sagt mir immer, dass z.B. der javac Befehl nicht gefunden werden kann.
Habs grad nochmal an ner simplen HelloWorld.java gestest.
muss JAVA_HOME auf das JDK Verzeichnis zeigen.
In der Systemvariablen %PATH% trage ich dann %JAVA_HOME%\bin ein um auf das bin-Verzeichnis des JDK zu zeigen. Nur hier befindet sich javac. Im JRE\bin befindet sich die javac nicht.
Ist aber auch egal wie herum ich es versuche, es klappt einfach nicht. Wie gesagt, das Theater hatte ich vor ein paar Wochen schon, als ich meine aller ersten java Konsolenprogramme ausführen wollte...
Du trägst JAVA_HOME doch als Benutzervariable und nicht als Systemvariable ein, oder?
Woran könnte es denn noch liegen?
JAVA_HOME zeigt auf das Verzeichnis in welchem man das JRE-Bin Verzeichnis findet (wer lesen kann, ist klar im Vorteil ). Das was du da gesetzt hast ist JDK_HOME welches afaik gar nicht mehr explizit angegeben werden muss. Lediglich der Pfad des JDK-Bin-Verzeichnisses muss noch in %PATH% aufgenommen werden wenn keine IDE wie Eclipse, Netbeans u.a. verwendet wird. Im %PATH% stehen somit dann beide Bin-Verzeichnisse. Ich trage das ganze als System-Variable ein. Das sollte aber keinen Unterschied machen.
* Name der Variablen: JAVA_HOME
* Wert der Variablen: Verzeichnis des JDKs (z.B.: CrogrammeJavajdk1.0.6_04)
Insofern lass ich mich hier nicht als Analphabeten abstempeln, hehe .
Dank deinem Hinweis hat es nun geklappt!! Allerdings war dazu scheinbar ein Neustart des Systems notwendig. Ist das immer so, wenn Systemvariablen verändert werden?
Jetzt gibts es aber erstmal ein offizielles Danke für dich !
Ich erhalte bei diversen Programmen, die ich über die Konsole ausführen will den NoClassDefFoundError.
Nun habe ich mehrfach gelesen, dass man in diesem Fall den Classpath als Umgebungsvariable setzen soll. Umgekehrt habe ich aber auch häufig gelesen, dass dies eigentlich gar nicht mehr notwendig sei, sofern die Klassen nicht aus dem standard-Verzeichnis des JDKs verschoben oder externe Klassen verwendet wurden.
Ein Beispiel:
Ich habe ein Projekt in folgendem Pfad vorliegen:
D:\...\app\transfer\TransferApp.class
Diese Klasse läd in ihrem Quellcode folgende Klassen:
Ahhh ja... V1.0.6 != V1.6.0... Druckfehler oder unheimlich alt? Seit Java1.2 (glaub' ich) sind JDK_HOME und JAVA_HOME zwei verschiedene Dinge. In dem einen Verzeichnis gibt es eine Unterverzeichnishierarchie [c]lib/ext[/c] (JRE) und in dem anderen nicht. [c]lib/ext[/c] ist der Grund, warum der CP nicht mehr unbedingt notwendig ist. JRE-Erweiterungen können einfach dort hinein kopiert werden.
Zu deiner App: Leider fehlen bei deinen Beispielen die Paketnamen, deswegen kann ich nur raten.
In Eclipse wird meistens ein Verzeichnis [c]src[/c] und ein Verzeichnis [c]bin[/c] erstellt. Darunter befindet sich dann direkt die Paketstruktur des Projektes. Ich gehe mal davon aus, dass du in das Verzeichnis [c]D:\...\app\transfer\[/c] wechselst und dann [c]java TransferApp[/c] aufrufst. Eine Klasse TransferApp existiert aber nicht, weil diese korrekt (und das ist jetzt geraten) "app.transfer.TransferApp" heisst. Das bedeutet, dass du vom [c]bin[/c] Verzeichnis ausgehend der Verzeichnisstruktur folgend (Verzeichnisnamen == Paketnamen) die Klasse ausführen musst. Das [c]bin[/c] Verzeichnis sei also das aktuelle Verzeichnis. Hier gibst du nun[c]java app.transfer.TransApp[/c] (ebenfalls geraten) ein.
Konnte jetzt erstmals den Shutdownhook testen und siehe da, funktioniert =)!
Den kompletten Package-Pfad anzugeben hatte ich vor einigen Tagen schonmal getestet, allerdings mit backslashes zwischen den Verzeichnissen und dann funzt es nicht. Geht scheinbar nur mit normalem Slash oder Punkten -.-
Nur eine Sache ist jetzt noch etwas verwunderlich und damit schließt sich der Kreis zum ursprünglichen Thema dieses Threads (Properties-Datei). Der Autor des Projektes setzt den Ordner prp, in dem die Properties Datei liegt auf dieselbe Ebene wie den bin Ordner. Wenn ich nun aber das Programm über die Shell ausführe, dann sucht er ja vergebens nach einem Ordner prp unterhalb von bin (siehe meinen geposteten Code am Anfang wo er die prp/transfer.properties laden soll).
Absolut korrekt. Aber das ist kein Fehler vom Autor, sondern Absicht. Möchte man die TransferApp als jar verbreiten, was ja gang und gebe ist, würde sich das Verzeichnis der Propertydatei innerhalb des Jar-Archieves nicht all zu gut machen, da ja srcDir und destDir veränderbar bleiben sollen. Man müsste bei jeder Änderung also das Archiv ändern (entpacken, ändern, neupacken). So wie der Autor das gemacht hat, lässt sich die Anwendung aus einer IDE heraus und als Jar-Archiv normal starten. Aus der Konsole heraus kommt in solchen Fällen dann wieder der gute alte CP zum tragen. Eine Verzeichnisebene höher, bin als CP und fertig.
Heißt das, dass ich den Classpath bis eine Ebene oberhalb von bin angeben muss und dann in der Shell z.B. java bin.net.app.transfer.TransferApp schreiben muss?
Zum CP: Der CP gibt doch quasi das Stammverzeichnis an, von dem aus die Packages mit ihren Klassen abgehen, richtig? Im CP selbst muss ja keine Klasse als Datei physisch vorhanden sein, oder? Der CP ist sozusagen nur der root zu allem was darunter liegt, richtig?
Heißt das, dass ich den Classpath bis eine Ebene oberhalb von bin angeben muss und dann in der Shell z.B. java bin.net.app.transfer.TransferApp schreiben muss?
Zum CP: Der CP gibt doch quasi das Stammverzeichnis an, von dem aus die Packages mit ihren Klassen abgehen, richtig? Im CP selbst muss ja keine Klasse als Datei physisch vorhanden sein, oder? Der CP ist sozusagen nur der root zu allem was darunter liegt, richtig?
Nö... Der Classpath der Pfad, in welchem die JVM seine "Anwendungen" sucht. Ist mehr mit der Umgebungsvariable "%PATH%" zu vergleichen. Ein im CP befindliches JAR kann von überall ausgeführt werden, natürlich nur, wenns korrekt ausführbar gemacht wurde.
Wenn ich schreibe: java -cp bin net.app.transfer.TransferApp
Bleibt der Wert der Variable cp dann eigentlich bestehen, oder gilt er nur für dieses eine Kommando?
gibts nen Unterschied zwischen -cp und -classpath ??