2009-02-21 5 views
66

Nella mia app java ho bisogno di ottenere alcuni file e directory.risorsa aperta con percorso relativo in java

Questa è la struttura del programma:

./main.java 
./package1/guiclass.java 
./package1/resources/resourcesloader.java 
./package1/resources/repository/modules/ -> this is the dir I need to get 
./package1/resources/repository/SSL-Key/cert.jks -> this is the file I need to get 

guiclass carichi della classe resourcesloader che caricherà le mie risorse (file e directory).

sul file, ho cercato

resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString() 

al fine di ottenere il percorso vero e proprio, ma in questo modo non funziona ...

Circa il dir non ho idea di come fare ..

Suggerimenti? Grazie.

+1

class.getClass() non è la stessa di class.getClassLoader(). Esiste anche un'altra soluzione, getResourceAsStream() che utilizza una classe nello stesso pacchetto della risorsa. Per maggiori dettagli: http://tshikatshikaaa.blogspot.nl/2012/07/maven-how-to-access-filesdata-in.html. – JVerstry

+0

Vedere anche http://stackoverflow.com/questions/204784/how-to-construct-a-relative-path-in-java-from-two-absolute-paths-or-slors – Vadzim

risposta

37

Fornire il percorso relativo al classloader, non alla classe da cui si ottiene il caricatore. Per esempio:

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString(); 
1

Hai fatto i seguenti lavori?

resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks") 

C'è un motivo per cui non è possibile specificare il percorso completo compreso il pacchetto?

2
resourcesloader.class.getClass() 

può essere suddiviso a:

Class<resourcesloader> clazz = resourceloader.class; 
Class<Class> classClass = clazz.getClass(); 

Il che significa che si sta cercando di caricare la risorsa utilizzando una classe di bootstrap.

Invece probabilmente desidera qualcosa di simile:

resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString() 

Se solo javac avvertito di chiamare i metodi statici in contesti non-statiche ...

7

Quando si utilizza 'getResource' su una classe, un parente il percorso viene risolto in base al pacchetto in cui si trova la classe. Quando si utilizza 'getResource' su un ClassLoader, viene risolto un percorso relativo basato sulla cartella principale.

Se si utilizza un percorso assoluto, entrambi i metodi 'getResource' inizieranno nella cartella principale.

+0

Non dimenticare gli effetti di '' '/' '' – Gilberto

+0

@nbeyer Perché usare 'getResource' con il percorso assoluto di avvio nella cartella principale? Lo scopo del percorso assoluto è ** assoluto **? –

126

Ho avuto problemi con l'utilizzo del metodo getClass().getResource("filename.txt"). Leggendo le istruzioni dei documenti Java, se la tua risorsa non si trova nello stesso pacchetto della classe a cui stai tentando di accedere alla risorsa, devi dargli il percorso relativo che inizia con '/'. La strategia raccomandata consiste nel mettere i file delle risorse in una cartella "risorse" nella directory principale.Così, per esempio, se si ha la struttura:

src/main/com/mycompany/myapp 

quindi è possibile aggiungere una cartella di risorse come raccomandato da Maven in:

src/main/resources 

, inoltre, è possibile aggiungere sottocartelle nella cartella risorse

src/main/resources/textfiles 

e dite che il vostro file si chiama myfile.txt quindi avete

src/main/resources/textfiles/myfile.txt 

Ora è qui che entra in gioco lo stupido problema. Dì che hai una classe nel tuo com.mycompany.myapp package e vuoi accedere al file myfile.txt dalla tua cartella delle risorse. Alcuni dicono che è necessario dare il:

"/main/resources/textfiles/myfile.txt" path 

o

"/resources/textfiles/myfile.txt" 

entrambi questi sono sbagliato. Dopo mi sono imbattuto mvn clean compile, i file e le cartelle vengono copiati in:

myapp/target/classes 

cartella. Ma la cartella delle risorse non è lì, solo le cartelle nella cartella delle risorse. In modo da avere:

myapp/target/classes/textfiles/myfile.txt 

myapp/target/classes/com/mycompany/myapp/* 

in modo che il percorso corretto che invia al metodo getClass().getResource("") è:

"/textfiles/myfile.txt" 

qui è:

getClass().getResource("/textfiles/myfile.txt") 

Questo non sarà più tornare null, ma sarà ritorna la tua classe. Spero che questo aiuti qualcuno. È strano per me che la cartella "resources" non venga copiata, ma solo le sottocartelle e i file direttamente nella cartella "resources". Sembrerebbe logico per me che la cartella "resources" sarebbe anche trovato sotto "myapp/target/classes"

+1

Nelle mie 'target/classi', posso vedere solo i file sotto le risorse principali e non le risorse di test. Perché? – Ava

+0

@Ava Aggiungi la cartella di test come cartella di origine e sei a posto! –

8

@GianCarlo: Si può provare a chiamare user.dir proprietà del sistema che vi darà radice del proprio progetto Java e quindi non aggiungere questo percorso per la vostra percorso relativo per esempio:

String root = System.getProperty("user.dir"); 
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt 
String abspath = root+filepath; 



// using above path read your file into byte [] 
File file = new File(abspath); 
FileInputStream fis = new FileInputStream(file); 
byte []filebytes = new byte[(int)file.length()]; 
fis.read(filebytes); 
+0

OP voleva individuare una risorsa nel classpath (molto probabilmente in un jar generato durante la compilazione). Questo metodo non fornisce un modo per raggiungere tale obiettivo: non è possibile puntare un 'File' a una risorsa all'interno di un file jar, ma solo a una voce appropriata nel file system (ad esempio, il jar stesso). – Attila

29

Nella speranza di fornire ulteriori informazioni per coloro che non raccolgono questo il più rapidamente gli altri, vorrei offrire il mio scenario in quanto ha una configurazione leggermente diversa. Il mio progetto è stato impostato con la seguente struttura di directory (con Eclipse):

 
Project/ 
    src/    // application source code 
    org/ 
     myproject/ 
     MyClass.java 
    test/    // unit tests 
    res/    // resources 
    images/   // PNG images for icons 
     my-image.png 
    xml/    // XSD files for validating XML files with JAXB 
     my-schema.xsd 
    conf/    // default .conf file for Log4j 
     log4j.conf 
    lib/    // libraries added to build-path via project settings 

stavo avendo problemi di caricamento mie risorse dalle res directory. Volevo che tutte le mie risorse si separassero dal mio codice sorgente (semplicemente per scopi di gestione/organizzazione).Quindi, quello che dovevo fare era aggiungere le res directory al accumulo percorso e poi accedere alla risorsa attraverso:

static final ClassLoader loader = MyClass.class.getClassLoader(); 

// in some function 
loader.getResource("images/my-image.png"); 
loader.getResource("xml/my-schema.xsd"); 
loader.getResource("conf/log4j.conf"); 

NOTA: Il / viene omesso dall'inizio del stringa di risorse perché sto utilizzando ClassLoader.getResource(String) anziché Class.getResource(String).

+1

. + 1 per suggerire ClassLoader – pyb

+0

La migliore risposta su questo argomento! Il consiglio di non usare '/' all'inizio di un percorso di risorsa era la chiave! – Kayhadrin

1

Proseguendo con le due risposte sopra menzionate. Il primo

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString(); 
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString() 

Dovrebbe essere una stessa cosa?

3

Per quelli che utilizzano eclipse + maven. Supponiamo che tu provi ad accedere al file images/pic.jpg in src/main/resources. In questo modo:

ClassLoader loader = MyClass.class.getClassLoader(); 
File file = new File(loader.getResource("images/pic.jpg").getFile()); 

è perfettamente corretto, ma può causare un'eccezione di puntatore nullo. Sembra che Eclipse non riconosca subito le cartelle nella struttura di directory di Maven come cartelle di origine. Rimuovendo e la cartella src/main/resources dall'elenco delle cartelle di origine del progetto e reinserendola (progetto> proprietà> percorso di configurazione java> origine> rimuovi/aggiungi cartella), sono stato in grado di risolverlo.

0

Ho apportato una piccola modifica sul liner di @ jonathan.cone (aggiungendo .getFile()) per evitare l'eccezione del puntatore nullo e impostare il percorso della directory dei dati. Ecco che cosa ha funzionato per me:

String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next(); 
0

Utilizzare questa:

resourcesloader.class.getClassLoader().getResource("/path/to/file").**getPath();**