2009-07-27 10 views
3

ich mit Code konfrontiert wurde, die einige Konfigurationsdateien aus dem Verzeichnis, in dem die .class-Datei selbst für die Klasse zu lesen versucht ist:Abrufen der Pfad zu dem Verzeichnis einer bestimmten Klasse Datei

File[] configFiles = new File(
    this.getClass().getResource(".").getPath()).listFiles(new FilenameFilter() { 
     public boolean accept(File dir, String name) { 
      return name.endsWith(".xml"); 
     } 
}); 

dies offenbar funktioniert in einigen Fällen (wenn der Code in Resin ausgeführt wird, vielleicht), aber für mich läuft Tomcat einfach mit NPE, weil getClass().getResource(".")null zurückgibt.

Ein Kollege schlug vor, eine weitere Konfigurationsdatei zu erstellen, die eine Liste aller ".xml" -Konfigurationsdateien enthält (was in der Tat funktionieren würde, da es ziemlich statisch bleibt), und Sie sollten nicht wirklich versuchen, so etwas zu tun Java.

Immer noch, ich frage mich, ob es einige nette Weise gibt, die universell funktioniert, um den Pfad zu dem Verzeichnis zu erhalten, in dem sich eine bestimmte .class-Datei befindet? Ich denke, man es aus dem Weg der .class-Datei selbst wie diese bekommen konnte:

new File(this.getClass().getResource("MyClass.class").getPath()).getParent() 

... aber ist dies der einzige/sauberste Weg?

bearbeiten: Um zu klären, gehen wir davon aus wissen dies in einer Anwendung in einer solchen Art und Weise eingesetzt wird verwendet, dass MyClass.class wird immer von einer Class-Datei auf der Festplatte gelesen werden, und die Ressourcen, da sein in das gleiche Verzeichnis.

+0

diese Frage im Zusammenhang gefunden: http://stackoverflow.com/questions/778187/getting-directory-path-to-class-file-containing-main Die akzeptierte Antwort nutzt im Grunde, was ich vorgeschlagen [getResource ("MyClass.class"). GetPath()] ... aber es beantwortet nicht direkt, ob das der einzige oder der beste Weg ist. – Jonik

Antwort

2

Was lässt Sie vermuten, dass sich eine Klassendatei auf der Festplatte in einem eigenen Verzeichnis befindet?

könnte eine Klasse sein:

  • Speicher vollständig in Erstellt
  • von einer Netzwerkverbindung Loaded
  • aus einer JAR-Datei
  • Loaded

Sie die URL der erstellen gewöhnen Klasse selbst, und wenn das mit file:// beginnt, dann könnten Sie den Rest bekommen ... aber es wird nicht für alle Klassen funktionieren.

+0

Ja, ich denke, das ist ziemlich genau das, was mein Kollege meinte, als ich die Alternative vorschlug ... Aber es gibt * Szenarien, in denen man weiß, dass die Klasse immer aus einer Datei auf der Festplatte geladen wird - wenn das der Fall ist Was habe ich in der Frage am saubersten vorgeschlagen? Danke für den Hinweis, dass Sie den Start der URL überprüfen! – Jonik

+0

Ja, was Sie da haben, sieht für mich am saubersten aus, wenn Sie das Dateiprotokoll überprüfen. –

2

Wenn sich die Ressource im selben Ordner befindet wie eine .class-Datei, sollte sie über den Klassenpfad zugänglich sein und kann direkt über getResourceAsStream geladen werden.

this.getClass().getResourceAsStream("filename.xml") 

Wie bereits gebucht wird, Klassen selbst geladen remote oder an Orten werden kann, wo es keine richtige „Weg“ (zB von einem jarfile)

+1

Ja, sicher; Ich war auf der Suche nach dem einfachsten Weg, um den Pfad * Verzeichnis * zu bekommen (weil wir mehrere Ressourcen-Dateien von dort lesen) – Jonik

+0

Ah versuchen Sie alle z. ".xml" Dateien aus dem Klassenpfad an diesem Punkt, ohne ihre Namen im Voraus wissen zu müssen? –

+1

Ja, das war hauptsächlich der Punkt. (Obwohl wir in diesem Fall die Namen im Grunde kennen, möchte ich nur die Dateien dynamisch lesen, um zu vermeiden, sie irgendwo aufzulisten oder so etwas.) – Jonik

1

ich mit Ihrem Kollegen einig, dass Java-Klasse Laden nicht war entworfen, um diesen Anwendungsfall zu behandeln. Sun Facelets verwendet eine ähnliche Strategie zur Annahme, dass URLs zu Dateien zugeordnet werden können, und es ist nicht schön. Ich stimme Jons Kommentar zu, dass Ihre getResource-Lösung unter Berücksichtigung Ihrer Bereitstellungsannahmen wahrscheinlich am saubersten ist. Da Sie gefragt haben, ob das der einzige Weg ist, werde ich auch getClass(). GetProtectionDomain(). GetCodeSource(). GetLocation() anbieten, was der URL sein sollte, von dem der Klassenlader tatsächlich Ihre Klasse geladen hat (Sie müssten das tun) Hängen Sie die Unterverzeichnisse für das Paket Ihrer Klasse an. Diese Strategie hat auch die gleichen URL-zu-Datei-Annahmen, also ist es in dieser Hinsicht nicht besser. Ich kann mir keine anderen allgemeinen Lösungen vorstellen.

Beachten Sie, dass getResource eine codierte URL zurückgibt, was bedeutet, dass Sie getPath() nicht direkt verwenden sollten.Insbesondere verursachen Leerzeichen Probleme, obwohl dies möglicherweise kein Problem ist, wenn Sie die Kontrolle über Ihre Umgebung haben. Erwägen Sie die Verwendung einer neuen Datei (URL.toURI()).

0

Ich denke, Sie könnten interessiert sein an PathMatchingResourcePatternResolver aus dem Spring Framework. Sie können es direkt in Ihrem Code zum Navigieren in den Konfigurationsdateien verwenden oder nach der Implementierung suchen here.

3

Ich weiß, dass dieser Thread alt ist, aber es ist das Top-Ergebnis in Google-Suchen, und es gab keine befriedigenden Antworten auf hier, für mich. Hier ist ein Code, den ich geschrieben habe, der großartig für mich funktioniert. Natürlich gibt es den Vorbehalt, dass es nicht von der Festplatte geladen wurde, aber es berücksichtigt das und gibt in diesem Fall null zurück. Dies funktioniert gut, um den "Container" zu finden, also den Stammort einer Klasse, sei es ein Jar oder ein Ordner. Dies passt möglicherweise nicht direkt zu Ihren Bedürfnissen. Wenn nicht, können Sie die Teile des Codes, die Sie benötigen, herausreißen.

/** 
* Returns the container url for this class. This varies based on whether or 
* not the class files are in a zip/jar or not, so this method standardizes 
* that. The method may return null, if the class is a dynamically generated 
* class (perhaps with asm, or a proxy class) 
* 
* @param c The class to find the container for 
* @return 
*/ 
public static String GetClassContainer(Class c) { 
    if (c == null) { 
     throw new NullPointerException("The Class passed to this method may not be null"); 
    } 
    try { 
     while(c.isMemberClass() || c.isAnonymousClass()){ 
      c = c.getEnclosingClass(); //Get the actual enclosing file 
     } 
     if (c.getProtectionDomain().getCodeSource() == null) { 
      //This is a proxy or other dynamically generated class, and has no physical container, 
      //so just return null. 
      return null; 
     } 
     String packageRoot; 
     try { 
      //This is the full path to THIS file, but we need to get the package root. 
      String thisClass = c.getResource(c.getSimpleName() + ".class").toString(); 
      packageRoot = StringUtils.replaceLast(thisClass, Pattern.quote(c.getName().replaceAll("\\.", "/") + ".class"), ""); 
      if(packageRoot.endsWith("!/")){ 
       packageRoot = StringUtils.replaceLast(packageRoot, "!/", ""); 
      } 
     } catch (Exception e) { 
      //Hmm, ok, try this then 
      packageRoot = c.getProtectionDomain().getCodeSource().getLocation().toString(); 
     } 
     packageRoot = URLDecoder.decode(packageRoot, "UTF-8"); 
     return packageRoot; 
    } catch (Exception e) { 
     throw new RuntimeException("While interrogating " + c.getName() + ", an unexpected exception was thrown.", e); 
    } 
} 
Verwandte Themen