risposta-alla-domanda-sullo-sviluppo-web-bd.com

getResourceAsStream restituisce null

Sto caricando un file di testo da un pacchetto in un JAR compilato del mio progetto Java. La struttura della directory pertinente è la seguente:

/src/initialization/Lifepaths.txt

Il codice utilizzato per caricare il file è:

public class Lifepaths {
    public static void execute() {
        System.out.println(Lifepaths.class.getClass().
            getResourceAsStream("/initialization/Lifepaths.txt"));
    }

    private Lifepaths() {}

    //This is temporary; will eventually be called from outside
    public static void main(String[] args) {execute();}
}

La stampa stamperà sempre null, indipendentemente da cosa io usi. Non sono sicuro del motivo per cui quanto sopra non avrebbe funzionato, quindi ho anche provato:

  • "/src/initialization/Lifepaths.txt"
  • "initialization/Lifepaths.txt"
  • "Lifepaths.txt"

Nessuno di questi lavori. Horeadmanyquestions finora sull'argomento, ma nessuno di loro è stato utile - di solito, dicono solo di caricare i file usando il root path, che Lo sto già facendo. Quello, o semplicemente caricare il file dalla directory corrente (basta caricare filename), che ho anche provato. Il file viene compilato nel JAR nella posizione appropriata con il nome appropriato. 

Come lo risolvo?

135
Zyerah

Lifepaths.class.getClass().getResourceAsStream(...) carica le risorse usando il caricatore di classi di sistema, ovviamente fallisce perché non vede i tuoi JAR

Lifepaths.class.getResourceAsStream(...) carica le risorse usando lo stesso programma di caricamento classe che ha caricato la classe Lifepaths e dovrebbe avere accesso alle risorse nei tuoi JAR

125
hoaz

Le regole sono le seguenti:

  1. controlla la posizione del file che vuoi caricare all'interno del JAR (e quindi assicurati che sia effettivamente aggiunto al JAR)
  2. utilizzare un percorso assoluto: il percorso inizia nella radice del JAR
  3. usa un percorso relativo: il percorso inizia nella directory del pacchetto della classe che stai chiamando getResource/getResoucreAsStream

E prova:

Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")

invece di

Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")

(non sono sicuro se faccia la differenza, ma il primo userà il ClassLoader/JAR corretto, mentre non sono sicuro con quest'ultimo)

50
Puce

Quindi ci sono diversi modi per ottenere una risorsa da un jar e ognuno ha una sintassi leggermente diversa in cui il percorso deve essere specificato in modo diverso.

La migliore spiegazione che ho visto è questo articolo di JavaWorld . Riassumo qui, ma se vuoi saperne di più, dai un'occhiata all'articolo.

Metodi

1) ClassLoader.getResourceAsStream()

Formato: "/" - nomi separati; no leading "/" (tutti i nomi sono assoluti). 

Esempio: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

2) Class.getResourceAsStream()

Formato: "/" - nomi separati; precedendo "/" indica i nomi assoluti; tutti gli altri nomi sono relativi al pacchetto della classe

Esempio: this.getClass().getResourceAsStream("/some/pkg/resource.properties");

40
greedybuddha

Non utilizzare percorsi assoluti, rendili relativi alla directory 'risorse' nel tuo progetto. Codice rapido e sporco che visualizza i contenuti di MyTest.txt dalla directory "risorse".

@Test
public void testDefaultResource() {
    // can we see default resources
    BufferedInputStream result = (BufferedInputStream) 
         Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
    byte [] b = new byte[256];
    int val = 0;
    String txt = null;
    do {
        try {
            val = result.read(b);
            if (val > 0) {
                txt += new String(b, 0, val);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } 
    } while (val > -1);
    System.out.println(txt);
}
12
Paul Smith

Potresti provare a fare questo per ottenere lo stream che prima raccoglie l'url e quindi lo apre come stream. 

URL url = getClass().getResource("/initialization/Lifepaths.txt"); 
InputStream strm = url.openStream(); 

Una volta ho avuto una domanda simile: La lettura del file txt da jar fallisce ma la lettura delle immagini funziona

9
MrD

Sembra che ci sia un problema con il ClassLoader che stai usando. Usa contextClassLoader per caricare la classe. Questo è indipendentemente dal fatto che sia in un metodo statico/non statico

Thread.currentThread().getContextClassLoader().getResourceAsStream......

6
Binita Bharati

Non so se di aiuto, ma nel mio caso ho avuto la mia risorsa nella cartella/src/e ricevevo questo errore . Ho quindi spostato l'immagine nella cartella bin e ha risolto il problema.

2
Leo Ufimtsev

Assicurati che la tua directory delle risorse (ad esempio "src") si trovi nel tuo classpath (assicurati che sia una directory di origine nel tuo percorso di build in Eclipse).

Assicurati che clazz sia caricato dal classloader principale.

Quindi, per caricare src/initialization/Lifepaths.txt, utilizzare 

clazz.getResourceAsStream("/initialization/Lifepaths.txt");

Perché: clazz.getResourcesAsStream(foo) cerca up da all'interno del classpath di clazz , relativo alla directory clazz vive in . Il "/" iniziale lo carica dalla radice di qualsiasi directory nel classpath di clazz.

A meno che tu non sia in un contenitore di qualche tipo, come Tomcat, o stia facendo qualcosa con ClassLoaders direttamente, puoi semplicemente considerare Eclipse/classpath come l'unico classpath del classloader.

2
Bobby Martin

Mi sono trovato in un problema simile. Dal momento che sto usando Maven, avevo bisogno di aggiornare il mio pom.xml per includere qualcosa del genere:

   ...
</dependencies>
<build>
    <resources>
        <resource>
            <directory>/src/main/resources</directory>
        </resource>
        <resource>
            <directory>../src/main/resources</directory>
        </resource>
    </resources>
    <pluginManagement>
        ...

Nota il tag di risorse in là per specificare dove si trova quella cartella. Se hai progetti annidati (come faccio io), potresti voler ottenere risorse da altre aree invece del solo modulo in cui stai lavorando. Ciò aiuta a ridurre la conservazione dello stesso file in ogni repository se stai utilizzando dati di configurazione simili 

1
plosco

Nel mio caso non ha funzionato a meno che non ho rimosso spazi dai nomi dei file ...

0
user3563159

Ciò che ha funzionato per me è stato aggiungere il file in My Project/Java Resources/src e quindi utilizzare 

this.getClass().getClassLoader().getResourceAsStream(myfile.txt);

Non ho avuto bisogno di aggiungere questo file al percorso (aggiungendolo a/src lo fa apparentemente)

0
Pablo