Domanda

Qual è la differenza tra:

InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName)

e

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)

e

InputStream is = this.getClass().getResourceAsStream(fileName)

Quando sono uno più appropriato da utilizzare rispetto agli altri?

Il file che voglio leggere è nel classpath come la mia classe che legge il file. La mia classe e il file sono nella stessa vaso e confezionati in un file EAR, e distribuito in WebSphere 6.1.

È stato utile?

Soluzione

Ci sono sottili differenze su come il fileName si sta passando viene interpretato. In sostanza, si hanno 2 differenti metodi: ClassLoader.getResourceAsStream() e Class.getResourceAsStream(). Questi due metodi saranno individuare la risorsa in modo diverso.

Nel Class.getResourceAsStream(path), il percorso viene interpretato come un percorso locale per il pacchetto della classe che si sta chiamando da. Per esempio chiamando, String.getResourceAsStream("myfile.txt") cercherà un file nel classpath al seguente indirizzo: "java/lang/myfile.txt". Se il percorso inizia con una /, allora sarà considerato un percorso assoluto, e inizierà a cercare dalla radice del classpath. Quindi chiamando String.getResourceAsStream("/myfile.txt") esaminerà il seguente percorso nel percorso di classe ./myfile.txt.

ClassLoader.getResourceAsStream(path) prenderà in considerazione tutti i percorsi di essere percorsi assoluti. Quindi chiamando String.getClassLoader().getResourceAsStream("myfile.txt") e String.getClassLoader().getResourceAsStream("/myfile.txt") saranno entrambi cercare un file nel classpath nel seguente percorso:. Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)

Ogni volta che ho citato una posizione in questo post, potrebbe essere una posizione nel file system per sé, o all'interno del file jar corrispondente, a seconda della classe e / o ClassLoader si sta caricando la risorsa da.

Nel tuo caso, si sta caricando la classe da un Application Server, in modo che le dovrebbe utilizzare this.getClass().getClassLoader().getResourceAsStream(fileName) invece di this.getClass().getResourceAsStream(). WebAppClassLoader funziona anche.

questo articolo per informazioni più dettagliate su questo particolare problema.


Attenzione per gli utenti di Tomcat 7 e al di sotto

Una delle risposte a questa domanda si afferma che la mia spiegazione sembra essere non corretta per Tomcat 7. Ho cercato di guardarsi intorno per vedere perché questo sarebbe il caso.

Così ho guardato il codice sorgente di Tomcat di findResource(String name) per diverse versioni di Tomcat. L'implementazione di classLoader.getResourceAsStream("/resource.txt") (che è responsabile della produzione utimately l'URL alla risorsa richiesta) è praticamente identica a Tomcat 6 e 7 Tomcat, ma è differente in Tomcat 8.

Nelle versioni 6 e 7, l'implementazione non tenta di normalizzare il nome della risorsa. Ciò significa che in queste versioni, classLoader.getResourceAsStream("resource.txt") potrebbero non produrre lo stesso risultato di class.getResourceAsStream("/resource.txt") evento se si deve (dato che ciò che il Javadoc specifica). [codice sorgente]

Nella versione 8, però, il nome della risorsa è normalizzato a garantire che la versione assoluta del nome della risorsa è quello che viene utilizzato. Pertanto, in Tomcat 8, le due chiamate sopra descritti devono sempre lo stesso risultato. [codice sorgente]

Di conseguenza, bisogna stare molto attenti quando si usano <=> o <=> sulle versioni di Tomcat prima di 8. E si deve anche tenere a mente che in realtà chiama <=> <=> (il principale <= > è spogliato).

Altri suggerimenti

Usa MyClass.class.getClassLoader().getResourceAsStream(path) per caricare risorsa associata con il codice. Utilizzare MyClass.class.getResourceAsStream(path) come una scorciatoia, e per le risorse confezionati all'interno del vostro pacchetto di classe.

Usa Thread.currentThread().getContextClassLoader().getResourceAsStream(path) per ottenere le risorse che fanno parte del codice del client, non strettamente limiti al codice chiamante. Si dovrebbe fare attenzione con questo come il caricatore di filo classe del contesto potrebbe essere rivolta a qualsiasi cosa.

Plain Old Java sulla pianura vecchio Java 7 e altre dipendenze dimostra la differenza ...

ho messo file.txt in c:\temp\ e ho messo <=> nel classpath.

C'è un solo caso in cui v'è una differenza tra i due chiamata.

class J {

 public static void main(String[] a) {
    // as "absolute"

    // ok   
    System.err.println(J.class.getResourceAsStream("/file.txt") != null); 

    // pop            
    System.err.println(J.class.getClassLoader().getResourceAsStream("/file.txt") != null); 

    // as relative

    // ok
    System.err.println(J.class.getResourceAsStream("./file.txt") != null); 

    // ok
    System.err.println(J.class.getClassLoader().getResourceAsStream("./file.txt") != null); 

    // no path

    // ok
    System.err.println(J.class.getResourceAsStream("file.txt") != null); 

   // ok
   System.err.println(J.class.getClassLoader().getResourceAsStream("file.txt") != null); 
  }
}

Tutte queste risposte qui intorno, così come le risposte in questa domanda , suggeriscono che il caricamento di URL assoluti, come "/ foo /bar.properties" trattati allo stesso modo da class.getResourceAsStream(String) e class.getClassLoader().getResourceAsStream(String). Questo non è il caso, almeno non nel mio Tomcat di configurazione / versione (al momento 7.0.40).

MyClass.class.getResourceAsStream("/foo/bar.properties"); // works!  
MyClass.class.getClassLoader().getResourceAsStream("/foo/bar.properties"); // does NOT work!

Siamo spiacenti, non ho assolutamente alcuna spiegazione soddisfacente, ma credo che Tomcat fa trucchi sporchi e la sua magia nera con i classloader e causare la differenza. Ho sempre usato <=> in passato e non ho avuto alcun problema.

PS: ho anche postato su qui

Dopo aver provato alcuni modi per caricare il file senza successo, mi sono ricordato che potrei usare FileInputStream, che ha funzionato perfettamente.

InputStream is = new FileInputStream("file.txt");

Questo è un altro modo per leggere un file in un InputStream, legge il file dalla cartella attualmente in esecuzione.

Funziona, provare questo:

InputStream in_s1 =   TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top