Comment charger un fichier à partir du dossier de ressources?

240

Mon projet a la structure suivante:

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

J'ai un fichier dans /src/test/resources/test.csvet je veux charger le fichier à partir d'un test unitaire dans/src/test/java/MyTest.java

J'ai ce code qui n'a pas fonctionné. Il se plaint "Aucun fichier ou répertoire de ce type".

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

J'ai aussi essayé

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

Cela ne fonctionne pas non plus. Il revient null. J'utilise Maven pour construire mon projet.

codereviewanskquestions
la source
Ça ne marche pas comment? Quelle est ton erreur?
Daniel Kaplan
17
essayez cecithis.getClass().getResource("/test.csv")
SRy
@SRy, cela a fonctionné (car cela donnera l'URL du chemin absolu en retour), mais au moment où je crée un fichier jar, cela ne fonctionne pas, car il se trouve dans un bocal et le chemin absolu devient invalide, existe-t-il un moyen de jouer avec le chemin relatif lui
ShankPossible

Réponses:

240

Essayez le suivant:

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

Si ce qui précède ne fonctionne pas, divers projets ont été ajoutés à la classe suivante: 1 (code ici ). 2ClassLoaderUtil

Voici quelques exemples d'utilisation de cette classe:

src \ main \ java \ com \ company \ 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
}

Remarques

  1. Voyez-le dans The Wayback Machine .
  2. Également dans GitHub .
Paul Vargas
la source
14
merci pour la réponse, pourriez-vous expliquer pourquoi nous devrions utiliser ce chargeur très spécifique mais pas celui de la classe?
Hui Wang
1
génial, je suis tellement stupide que j'utilisais Object.class.getClassLoader();, à partir d'un contexte statique qui ne fonctionnait pas - cette suggestion fait - enfin presque, elle injecte %20pour les espaces qui me donneFileNotFoundException
ycomp
5
@ycomp Parce que getResource renvoie une URL, pas un fichier. La méthode getFile de java.net.URL ne convertit pas une URL en fichier; il renvoie simplement le chemin et les parties de requête de l'URL. Vous ne devriez même pas essayer de le convertir en fichier; appelez simplement openStream et lisez à partir de cela.
VGR
Vérifiez ce projet, résout l'analyse des dossiers de ressources: github.com/fraballi/resources-folder-scanner
Felix Aballi
60

Essayer:

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

IIRC getResourceAsStream()par défaut est relatif au package de la classe.

Comme l'a noté @Terran, n'oubliez pas d'ajouter le /au début du nom de fichier

vanza
la source
3
Pour ceux qui recherchent la raison, ce message vous apporte tout le chemin pour obtenir la ressource en tant que String stackoverflow.com/a/35446009/544045
Trevor
12
Le "/" est la clé.
Terran
33

Voici une solution rapide avec l'utilisation de la goyave :

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);
}

Usage:

String fixture = this.readResource("filename.txt", Charsets.UTF_8)
Datageek
la source
28

Essayez les codes fluides sur le projet Spring

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

Ou sur un projet non printanier

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);
srsajid
la source
Le InputStream ne doit-il pas être fermé?
030
7

Projet non printanier:

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

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

Pour les projets Spring, vous pouvez également utiliser un code de ligne pour obtenir n'importe quel fichier dans le dossier de ressources:

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

String content = new String(Files.readAllBytes(file.toPath()));
Fuat
la source
5

Maintenant, j'illustre le code source pour lire une police à partir du répertoire de ressources créé par maven,

scr / main / resources / calibril.ttf

entrez la description de l'image ici

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;
}

Cela a fonctionné pour moi et j'espère que le code source entier vous aidera également, profitez-en!

ArifMustafa
la source
5

Pour java après 1.7

 List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));
phray2002
la source
Je dois utiliser "/test.csv" (notez la barre oblique).
Leon
4
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

Si vous utilisez ClassLoader contextuel pour trouver une ressource, cela coûtera certainement les performances de l'application.

Bimales Mandal
la source
4
Les programmeurs doivent toujours se soucier des performances. Bien qu'une optimisation prématurée soit certainement à éviter, connaître l'approche la plus efficace à adopter est toujours une bonne chose. C'est comme connaître la différence entre LinkedList et ArrayList et quand utiliser l'un ou l'autre.
mars 2015
6
@Marvo: Les programmeurs doivent toujours se soucier de la qualité, des capacités et de la facilité de maintenance, les performances sont au rendez-vous.
Igor Rodriguez
2

Importez les éléments suivants:

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

La méthode suivante renvoie un fichier dans une 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;
}
shalamus
la source
2

J'ai fait face au même problème .

Le fichier n'a pas été trouvé par un chargeur de classe, ce qui signifie qu'il n'a pas été compressé dans l'artefact (jar). Vous devez construire le projet . Par exemple, avec maven:

mvn clean install

Ainsi, les fichiers que vous avez ajoutés au dossier de ressources entreront dans la construction maven et deviendront disponibles pour l'application.

Je voudrais garder ma réponse: elle n'explique pas comment lire un fichier (d'autres réponses l'expliquent), elle répond pourquoi InputStream ou resourceétait nulle . Une réponse similaire est ici .

Yan Khonski
la source
1
Merci, ça m'a évité de penser que je perdais la tête!
StuPointerException
1

getResource () fonctionnait bien avec les fichiers de ressources placés src/main/resourcesuniquement. Pour obtenir un fichier qui se trouve sur le chemin autre que src/main/resourcesdire, src/test/javavous devez le créer exlicitement.

l'exemple suivant peut vous aider

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")));
    }
}
Piyush Mittal
la source
0

Le code fonctionne-t-il lorsque vous n'exécutez pas le pot Maven-build, par exemple lors de l'exécution à partir de votre IDE? Si c'est le cas, assurez-vous que le fichier est réellement inclus dans le bocal. Le dossier des ressources doit être inclus dans le fichier pom, dans <build><resources>.

Jorn
la source
Lorsque vous utilisez eclipse et exécutez du code à partir d'IDE lui-même. Comment pouvons-nous charger des ressources situées dans "/ src / test / resources" dans le code Java spécifiquement dans les tests unitaires. Considérons une structure de projet maven standard.
Bhavesh
0

La classe suivante peut être utilisée pour charger un resourcedepuis le classpathet recevoir également un message d'erreur approprié en cas de problème avec le donné 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;
    }
}
BullyWiiPlaza
la source
0

J'ai résolu ce problème en ajoutant un /scr/main/resourcesdossier à monJava Build Path

entrez la description de l'image ici

sklimkovitch
la source
essayez ceci mais ce n'est pas la solution
Jasonw
0

Je l'ai fait fonctionner à la fois sur le pot en cours d'exécution et dans l'IDE en écrivant comme

 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);
rakeeee
la source
À quoi ressemble la structure de vos fichiers?
luckydonald
0
this.getClass().getClassLoader().getResource("filename").getPath()
shiva kumar
la source
0

Vous pouvez utiliser com.google.common.io.Resources.getResource pour lire l'url du fichier, puis obtenir le contenu du fichier à l'aide de java.nio.file.Files pour lire le contenu du fichier.

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

Je le fais fonctionner sans aucune référence à "class" ou "ClassLoader".

Disons que nous avons trois scénarios avec l'emplacement du fichier 'example.file' et votre répertoire de travail (où votre application s'exécute) est home / mydocuments / program / projects / myapp:

a) Un sous-dossier descendant vers le répertoire de travail: myapp / res / files / example.file

b) Un sous-dossier non descendant vers le répertoire de travail: projets / fichiers / exemple.fichier

b2) Un autre sous-dossier non descendant du répertoire de travail: programme / fichiers / exemple.fichier

c) Un dossier racine: home / mydocuments / files / example.file (Linux; sous Windows remplacez home / par C :)

1) Obtenez le bon chemin: 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"

Fondamentalement, s'il s'agit d'un dossier racine, démarrez le nom du chemin avec une barre oblique. S'il s'agit d'un sous-dossier, aucune barre oblique ne doit précéder le nom du chemin. Si le sous-dossier n'est pas descendant vers le répertoire de travail, vous devez y accéder en utilisant "../". Cela indique au système de remonter d'un dossier.

2) Créez un objet File en passant le bon chemin:

File file = new File(path);

3) Vous êtes maintenant prêt à partir:

BufferedReader br = new BufferedReader(new FileReader(file));
AndreGraveler
la source