getResourceAsStream restituisce null

Sto caricando un file di testo dall'interno di un pacchetto in un JAR compilato del mio progetto Java. La struttura della directory in questione è 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 viene sempre stampata su null, non importa cosa uso. Non sono sicuro del perché quanto sopra non funzioni, quindi ho anche provato:

  • "/src/initialization/Lifepaths.txt"
  • "inizializzazione/Lifepaths.txt"
  • "Percorsi vita.txt"

Nessuno di questi funziona. Ho letto numerose domande finora sull'argomento, ma nessuna di esse è stata utile - di solito, dicono solo di caricare i file usando il percorso principale, che sto già facendo. Questo, o semplicemente caricare il file dalla directory corrente (solo load filename), che ho anche provato. Il file viene compilato nel JAR nella posizione appropriata con il nome appropriato.

Come posso risolvere questo problema?

Soluzione

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

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

Commentari (6)

Le regole sono le seguenti:

  1. controllare la posizione del file che si vuole caricare all'interno del JAR (e quindi assicurarsi anche che sia stato effettivamente aggiunto al JAR)
  2. usare un percorso assoluto: il percorso inizia dalla radice del JAR
  3. usare un percorso relativo: il percorso inizia dalla 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 che faccia differenza, ma il primo userà il corretto ClassLoader/ JAR, mentre non sono sicuro con il secondo)

Commentari (3)

Quindi ci sono diversi modi per ottenere una risorsa da un barattolo 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 da JavaWorld. Riassumerò qui, ma se volete saperne di più dovreste controllare l'articolo.

Metodi

  1. ClassLoader.getResourceAsStream().

Formato: "/"-nomi separati; nessun "/" iniziale (tutti i nomi sono assoluti).

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

  1. Class.getResourceAsStream()

Formato: "/"-nomi separati; l'iniziale "/" indica nomi assoluti; tutti gli altri nomi sono relativi al pacchetto della classe

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

Commentari (3)