Wie lade ich eine Datei aus dem Ressourcenordner?

240

Mein Projekt hat folgende Struktur:

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

Ich habe eine Datei in /src/test/resources/test.csvund möchte die Datei von einem Unit-Test in laden/src/test/java/MyTest.java

Ich habe diesen Code, der nicht funktioniert hat. Es beschwert sich "Keine solche Datei oder Verzeichnis".

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

Ich habe es auch versucht

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

Das funktioniert auch nicht. Es kehrt zurück null. Ich benutze Maven, um mein Projekt zu erstellen.

codereviewanskquestions
quelle
Funktioniert nicht wie? Was ist dein Fehler?
Daniel Kaplan
16
versuchen Sie diesthis.getClass().getResource("/test.csv")
SRy
@SRy es hat funktioniert (weil dies im Gegenzug eine absolute Pfad-URL ergibt), aber sobald ich eine JAR-Datei erstelle, funktioniert sie nicht, da sie sich in einem JAR befindet und der absolute Pfad ungültig wird. Es gibt eine Möglichkeit, mit dem relativen Pfad selbst zu spielen
ShankPossible

Antworten:

240

Versuchen Sie das nächste:

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

Wenn das oben genannte nicht funktioniert, wurden verschiedene Projekte der folgenden Klasse hinzugefügt: 1 (Code hier ). 2ClassLoaderUtil

Hier einige Beispiele für die Verwendung dieser Klasse:

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
}

Anmerkungen

  1. Sehen Sie es in The Wayback Machine .
  2. Auch in GitHub .
Paul Vargas
quelle
14
Danke für die Antwort, können Sie bitte erklären, warum wir diesen sehr spezifischen Lader verwenden sollten, aber nicht den der Klasse?
Hui Wang
1
großartig, ich bin so dumm, dass ich Object.class.getClassLoader();aus einem statischen Kontext, der nicht funktioniert hat - dieser Vorschlag funktioniert - nun, fast, er spritzt %20für Leerzeichen, die mir einenFileNotFoundException
ycomp
5
@ycomp Da getResource eine URL zurückgibt, keine Datei. Die getFile Methode der java.net.URL nicht eine URL zu einer Datei konvertieren; Es werden nur die Pfad- und Abfrageteile der URL zurückgegeben. Sie sollten nicht einmal versuchen, es in eine Datei zu konvertieren. Rufen Sie einfach openStream auf und lesen Sie daraus.
VGR
Überprüfen Sie dieses Projekt und lösen Sie das Scannen von Ressourcenordnern: github.com/fraballi/resources-folder-scanner
Felix Aballi
60

Versuchen:

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

IIRC ist getResourceAsStream()standardmäßig relativ zum Paket der Klasse.

Wie @Terran bemerkt hat, vergessen Sie nicht, das /am Anfang des Dateinamens hinzuzufügen

Vanza
quelle
3
Für diejenigen, die nach Vernunft suchen, bietet dieser Beitrag den ganzen Weg, um die Ressource als String stackoverflow.com/a/35446009/544045
Trevor
12
Das "/" ist der Schlüssel.
Terraner
33

Hier ist eine schnelle Lösung mit 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);
}

Verwendung:

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

Probieren Sie Flowing Codes für das Spring-Projekt aus

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

Oder bei einem Projekt außerhalb des Frühlings

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);
srsajid
quelle
Sollte der InputStream nicht geschlossen werden?
030
6

Nicht-Frühlingsprojekt:

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

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

Für Frühjahrsprojekte können Sie auch einen Zeilencode verwenden, um eine beliebige Datei im Ressourcenordner abzurufen:

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

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

Jetzt illustriere ich den Quellcode zum Lesen einer Schriftart aus einem von Maven erstellten Ressourcenverzeichnis.

scr / main / resources / kalibril.ttf

Geben Sie hier die Bildbeschreibung ein

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

Es hat bei mir funktioniert und ich hoffe, dass der gesamte Quellcode Ihnen auch hilft. Viel Spaß!

ArifMustafa
quelle
5

Für Java nach 1.7

 List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));
phray2002
quelle
Ich muss "/test.csv" verwenden (beachten Sie den Schrägstrich).
Leon
4
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

Wenn Sie den Kontext ClassLoader verwenden, um eine Ressource zu finden, kostet dies definitiv die Anwendungsleistung.

Bimales Mandal
quelle
4
Programmierer sollten immer über die Leistung besorgt sein. Während eine vorzeitige Optimierung sicherlich vermieden werden sollte, ist es immer gut, den effizienteren Ansatz zu kennen. Es ist, als würde man den Unterschied zwischen LinkedList und ArrayList kennen und wissen, wann man die eine oder andere verwenden soll.
Marvo
6
@Marvo: Programmierer müssen sich immer um Qualität, Fähigkeiten und Wartungsfreundlichkeit sorgen. Die Leistung steht an erster Stelle.
Igor Rodriguez
2

Importieren Sie Folgendes:

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

Die folgende Methode gibt eine Datei in einer ArrayList of Strings zurück:

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
quelle
2

Ich stand vor dem gleichen Problem .

Die Datei wurde von einem Klassenladeprogramm nicht gefunden, was bedeutet, dass sie nicht in das Artefakt (jar) gepackt wurde. Sie müssen das Projekt erstellen . Zum Beispiel mit maven:

mvn clean install

Die Dateien, die Sie dem Ressourcenordner hinzugefügt haben, werden in den Maven-Build übernommen und stehen der Anwendung zur Verfügung.

Ich möchte meine Antwort behalten: Es erklärt nicht, wie man eine Datei liest (andere Antworten erklären das), es antwortet, warum InputStream oder resourcewar null . Eine ähnliche Antwort gibt es hier .

Yan Khonski
quelle
1
Danke, hat mich davor bewahrt zu glauben, ich hätte den Verstand verloren!
StuPointerException
1

getResource () funktionierte einwandfrei mit den src/main/resourcesnur darin abgelegten Ressourcendateien . Um eine Datei zu erhalten, die sich auf einem anderen Pfad als dem angegebenen befindet src/main/resources, müssen src/test/javaSie sie explizit erstellen.

Das folgende Beispiel kann Ihnen helfen

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
quelle
0

Funktioniert der Code, wenn das Maven-Build-JAR nicht ausgeführt wird, z. B. wenn es von Ihrer IDE ausgeführt wird? Wenn ja, stellen Sie sicher, dass die Datei tatsächlich im JAR enthalten ist. Der Ressourcenordner sollte in der POM-Datei enthalten sein <build><resources>.

Jorn
quelle
Bei Verwendung von Eclipse und Ausführen von Code aus der IDE selbst. Wie können wir Ressourcen unter "/ src / test / resources" in Java-Code speziell in Unit-Tests laden? Betrachten Sie eine Standard-Maven-Projektstruktur.
Bhavesh
0

Die folgende Klasse kann verwendet werden, um eine resourcevon der zu laden classpathund eine passende Fehlermeldung zu erhalten, falls ein Problem mit der angegebenen Klasse vorliegt 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
quelle
0

Ich habe dieses Problem gelöst, indem ich /scr/main/resourcesmeinem Ordner einen Ordner hinzugefügt habeJava Build Path

Geben Sie hier die Bildbeschreibung ein

sklimkovitch
quelle
Versuchen Sie dies, aber dies ist nicht die Lösung
Jasonw
0

Ich habe es sowohl auf Running Jar als auch in IDE zum Laufen gebracht, indem ich als geschrieben habe

 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
quelle
Wie sieht Ihre Dateistruktur aus?
Luckydonald
0
this.getClass().getClassLoader().getResource("filename").getPath()
Shiva Kumar
quelle
0

Sie können com.google.common.io.Resources.getResource verwenden, um die URL der Datei zu lesen, und dann den Dateiinhalt mit java.nio.file.Files abrufen, um den Inhalt der Datei zu lesen.

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

Ich lasse es funktionieren, ohne auf "class" oder "ClassLoader" zu verweisen.

Angenommen, wir haben drei Szenarien mit dem Speicherort der Datei 'example.file' und Ihrem Arbeitsverzeichnis (in dem Ihre App ausgeführt wird) ist home / mydocuments / program / projects / myapp:

a) Ein Unterordner des Arbeitsverzeichnisses: myapp / res / files / example.file

b) Ein Unterordner, der nicht vom Arbeitsverzeichnis abstammt: projects / files / example.file

b2) Ein weiterer Unterordner, der nicht vom Arbeitsverzeichnis abstammt: program / files / example.file

c) Ein Stammordner: home / mydocuments / files / example.file (Linux; unter Windows ersetzen Sie home / durch C :)

1) Holen Sie sich den richtigen Weg: 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"

Wenn es sich um einen Stammordner handelt, beginnen Sie den Pfadnamen grundsätzlich mit einem führenden Schrägstrich. Wenn es sich um einen Unterordner handelt, darf vor dem Pfadnamen kein Schrägstrich stehen. Wenn der Unterordner nicht vom Arbeitsverzeichnis abstammt, müssen Sie ihn mit "../" aufrufen. Dies weist das System an, einen Ordner nach oben zu verschieben.

2) Erstellen Sie ein Dateiobjekt, indem Sie den richtigen Pfad übergeben:

File file = new File(path);

3) Sie können jetzt loslegen:

BufferedReader br = new BufferedReader(new FileReader(file));
AndreGraveler
quelle