Come carico un file dalla cartella delle risorse?


240

Il mio progetto ha la seguente struttura:

/src/main/java/
/src/main/resources/
/src/test/java/
/src/test/resources/

Ho un file in /src/test/resources/test.csve voglio caricare il file da un test unitario in/src/test/java/MyTest.java

Ho questo codice che non ha funzionato. Si lamenta "Nessun file o directory".

BufferedReader br = new BufferedReader (new FileReader(test.csv))

Ho anche provato questo

InputStream is = (InputStream) MyTest.class.getResourcesAsStream(test.csv))

Anche questo non funziona. Ritorna null. Sto usando Maven per costruire il mio progetto.


Non funziona come? Qual è il tuo errore?
Daniel Kaplan,

17
prova questothis.getClass().getResource("/test.csv")
SRy


@Ry ha funzionato (perché questo restituirà l'URL del percorso assoluto in cambio) tuttavia nel momento in cui creo il file jar non funziona poiché si trova all'interno di un jar e il percorso assoluto diventa non valido, c'è un modo per giocare con il relativo percorso stesso
ShankPossible

Risposte:


240

Prova il prossimo:

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("test.csv");

Se quanto sopra non funziona, sono stati aggiunti vari progetti alla seguente classe: 1 (codice qui ). 2ClassLoaderUtil

Ecco alcuni esempi di come viene utilizzata quella classe:

src \ Main \ java \ com \ società \ test \ YourCallingClass.java
src \ Main \ java \ com \ OpenSymphony \ xwork2 \ util \ ClassLoaderUtil.java
src \ Main \ Resources \ test.csv
// java.net.URL
URL url = ClassLoaderUtil.getResource("test.csv", YourCallingClass.class);
Path path = Paths.get(url.toURI());
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// java.io.InputStream
InputStream inputStream = ClassLoaderUtil.getResourceAsStream("test.csv", YourCallingClass.class);
InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(streamReader);
for (String line; (line = reader.readLine()) != null;) {
    // Process line
}

Appunti

  1. Guardalo in The Wayback Machine .
  2. Anche in GitHub .

14
grazie per la risposta, potresti spiegare perché dovremmo usare questo caricatore molto specifico ma non quello della classe?
Hui Wang,

1
fantastico, sono così stupido che stavo usando Object.class.getClassLoader();, da un contesto statico che non ha funzionato - questo suggerimento funziona - beh quasi, inietta %20spazi che mi danno unFileNotFoundException
ycomp

5
@ycomp Perché getResource restituisce un URL, non un file. Il metodo getFile di java.net.URL non converte un URL in un file; restituisce semplicemente il percorso e interroga parti dell'URL. Non dovresti nemmeno provare a convertirlo in un File; basta chiamare openStream e leggere da quello.
VGR

Controlla questo progetto, risolve la scansione della cartella delle risorse: github.com/fraballi/resources-folder-scanner
Felix Aballi

60

Provare:

InputStream is = MyTest.class.getResourceAsStream("/test.csv");

IIRC getResourceAsStream()per impostazione predefinita è relativo al pacchetto della classe.

Come notato da @Terran, non dimenticare di aggiungere /all'inizio del nome file


3
Per coloro che cercano sanità mentale, questo post ti porta fino in fondo per ottenere la risorsa come String stackoverflow.com/a/35446009/544045
Trevor

12
"/" È la chiave.
Terran

33

Ecco una soluzione rapida con l'uso di Guava :

import com.google.common.base.Charsets;
import com.google.common.io.Resources;

public String readResource(final String fileName, Charset charset) throws IOException {
        return Resources.toString(Resources.getResource(fileName), charset);
}

Uso:

String fixture = this.readResource("filename.txt", Charsets.UTF_8)

28

Prova i codici Flowing sul progetto Spring

ClassPathResource resource = new ClassPathResource("fileName");
InputStream inputStream = resource.getInputStream();

O su un progetto non primaverile

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);

InputStream non deve essere chiuso?
030,

7

Progetto non primaverile:

String filePath = Objects.requireNonNull(MyClass.class.getClassLoader().getResource("any.json")).getPath();

Stream<String> lines = Files.lines(Paths.get(filePath));

Per i progetti di primavera, puoi anche utilizzare un codice di riga per ottenere qualsiasi file nella cartella delle risorse:

File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "any.json");

String content = new String(Files.readAllBytes(file.toPath()));

5

Ora sto illustrando il codice sorgente per la lettura di un font dalla directory delle risorse create da Maven,

scr / main / risorse / calibril.ttf

inserisci qui la descrizione dell'immagine

Font getCalibriLightFont(int fontSize){
    Font font = null;
    try{
        URL fontURL = OneMethod.class.getResource("/calibril.ttf");
        InputStream fontStream = fontURL.openStream();
        font = new Font(Font.createFont(Font.TRUETYPE_FONT, fontStream).getFamily(), Font.PLAIN, fontSize);
        fontStream.close();
    }catch(IOException | FontFormatException ief){
        font = new Font("Arial", Font.PLAIN, fontSize);
        ief.printStackTrace();
    }   
    return font;
}

Ha funzionato per me e spero che anche l'intero codice sorgente ti aiuti, divertiti!


5

Per java dopo 1.7

 List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));

Devo usare "/test.csv" (notare la barra).
Leon,

4
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

Se usi il contesto ClassLoader per trovare una risorsa, sicuramente costerà le prestazioni dell'applicazione.


4
I programmatori dovrebbero essere sempre preoccupati per le prestazioni. Mentre l'ottimizzazione prematura deve certamente essere evitata, è sempre bene conoscere l'approccio più efficiente da adottare. È come conoscere la differenza tra LinkedList e ArrayList e quando usare l'uno o l'altro.
Marvo,

6
@Marvo: i programmatori devono sempre preoccuparsi di qualità, capacità e facilità di manutenzione, le prestazioni sono in coda.
Igor Rodriguez,

2

Importa quanto segue:

import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.ArrayList;

Il seguente metodo restituisce un file in un ArrayList of Strings:

public ArrayList<String> loadFile(String filename){

  ArrayList<String> lines = new ArrayList<String>();

  try{

    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    InputStream inputStream = classloader.getResourceAsStream(filename);
    InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    BufferedReader reader = new BufferedReader(streamReader);
    for (String line; (line = reader.readLine()) != null;) {
      lines.add(line);
    }

  }catch(FileNotFoundException fnfe){
    // process errors
  }catch(IOException ioe){
    // process errors
  }
  return lines;
}

2

Ho affrontato lo stesso problema .

Il file non è stato trovato da un programma di caricamento classi, il che significa che non è stato compresso nell'artefatto (jar). Devi costruire il progetto . Ad esempio, con Maven:

mvn clean install

Quindi i file aggiunti alla cartella delle risorse entreranno in maven build e diventeranno disponibili per l'applicazione.

Vorrei mantenere la mia risposta: non spiega come leggere un file (altre risposte lo spiegano), risponde perché InputStream o resourceera nullo . Una risposta simile è qui .


1
Grazie, mi ha salvato dal pensare che stavo perdendo la testa!
StuPointerException il

1

getResource () funzionava bene solo con i file di risorse inseriti src/main/resources. Per ottenere un file che si trova sul percorso diverso da src/main/resourcesdire src/test/javaè necessario crearlo esplicitamente.

il seguente esempio può aiutarti

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws URISyntaxException, IOException {
        URL location = Main.class.getProtectionDomain().getCodeSource().getLocation();
        BufferedReader br = new BufferedReader(new FileReader(location.getPath().toString().replace("/target/classes/", "/src/test/java/youfilename.txt")));
    }
}

0

Il codice funziona quando non si esegue il jar Maven-build, ad esempio quando si esegue dal proprio IDE? In tal caso, assicurati che il file sia effettivamente incluso nel vaso. La cartella delle risorse dovrebbe essere inclusa nel file pom, in <build><resources>.


Quando si utilizza eclipse e si esegue il codice dall'IDE stesso. Come possiamo caricare risorse che si trovano in "/ src / test / resources" nel codice Java specificamente nei test unitari. Considera una struttura di progetto standard maven.
Bhavesh,

0

La seguente classe può essere utilizzata per caricare un resourceda classpathe anche ricevere un messaggio di errore appropriato nel caso in cui ci sia un problema con il dato filePath.

import java.io.InputStream;
import java.nio.file.NoSuchFileException;

public class ResourceLoader
{
    private String filePath;

    public ResourceLoader(String filePath)
    {
        this.filePath = filePath;

        if(filePath.startsWith("/"))
        {
            throw new IllegalArgumentException("Relative paths may not have a leading slash!");
        }
    }

    public InputStream getResource() throws NoSuchFileException
    {
        ClassLoader classLoader = this.getClass().getClassLoader();

        InputStream inputStream = classLoader.getResourceAsStream(filePath);

        if(inputStream == null)
        {
            throw new NoSuchFileException("Resource file not found. Note that the current directory is the source folder!");
        }

        return inputStream;
    }
}

0

Ho risolto questo problema aggiungendo una /scr/main/resourcescartella alla miaJava Build Path

inserisci qui la descrizione dell'immagine


prova questo, ma questa non è la soluzione
Jasonw,

0

L'ho fatto funzionare sia su jar in esecuzione che in IDE scrivendo come

 InputStream schemaStream = ProductUtil.class.getClassLoader().getResourceAsStream(jsonSchemaPath);
            byte[] buffer = new byte[schemaStream.available()];
            schemaStream.read(buffer);

        File tempFile = File.createTempFile("com/package/schema/testSchema", "json");
        tempFile.deleteOnExit();
        FileOutputStream out = new FileOutputStream(tempFile);
        out.write(buffer);

Come appare la struttura dei tuoi file?
luckydonald

0
this.getClass().getClassLoader().getResource("filename").getPath()

0

Puoi utilizzare com.google.common.io.Resources.getResource per leggere l'URL del file e quindi ottenere il contenuto del file utilizzando java.nio.file.Files per leggere il contenuto del file.

URL urlPath = Resources.getResource("src/main/resource");
List<String> multilineContent= Files.readAllLines(Paths.get(urlPath.toURI()));

-2

Lo faccio funzionare senza alcun riferimento a "class" o "ClassLoader".

Diciamo che abbiamo tre scenari con la posizione del file 'esempio.file' e la tua directory di lavoro (dove viene eseguita la tua app) è home / mydocuments / program / projects / myapp:

a) Una sottocartella che discende dalla directory di lavoro: myapp / res / files / example.file

b) Una sottocartella non discendente dalla directory di lavoro: progetti / file / esempio. file

b2) Un'altra sottocartella non discendente dalla directory di lavoro: program / files / example.file

c) Una cartella principale: home / mydocuments / files / example.file (Linux; in Windows sostituisci home / con C :)

1) Prendi la strada giusta: a) String path = "res/files/example.file"; b) String path = "../projects/files/example.file" b2) String path = "../../program/files/example.file" c)String path = "/home/mydocuments/files/example.file"

Fondamentalmente, se si tratta di una cartella principale, avviare il nome del percorso con una barra iniziale. Se si tratta di una sottocartella, nessuna barra deve essere prima del nome del percorso. Se la sottocartella non discende dalla directory di lavoro, è necessario eseguirne il cd utilizzando "../". Questo dice al sistema di salire di una cartella.

2) Crea un oggetto File passando il percorso giusto:

File file = new File(path);

3) Ora sei a posto:

BufferedReader br = new BufferedReader(new FileReader(file));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.