Jak załadować plik z folderu zasobów?


240

Mój projekt ma następującą strukturę:

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

Mam plik /src/test/resources/test.csvi chcę go załadować z testu jednostkowego/src/test/java/MyTest.java

Mam ten kod, który nie działał. Narzeka „Brak takiego pliku lub katalogu”.

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

Próbowałem też tego

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

To też nie działa. Powraca null. Używam Maven do budowy mojego projektu.


Nie działa jak? Jaki masz błąd?
Daniel Kaplan

17
spróbuj tegothis.getClass().getResource("/test.csv")
2013


@SRy to zadziałało (bo to da w zamian adres URL ścieżki bezwzględnej), jednak w chwili, gdy utworzę plik jar, nie działa, ponieważ znajduje się w słoiku i ścieżka bezwzględna staje się nieprawidłowa, istnieje sposób na grę z samą ścieżką względną
ShankPossible

Odpowiedzi:


240

Wypróbuj następną:

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

Jeśli powyższe nie działa, do różnych projektów dodano następującą klasę: 1 (kod tutaj ). 2)ClassLoaderUtil

Oto kilka przykładów użycia tej klasy:

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
}

Notatki

  1. Zobacz to w The Wayback Machine .
  2. Również w GitHub .

14
dziękuję za odpowiedź, czy mógłbyś wyjaśnić, dlaczego powinniśmy używać tego bardzo konkretnego modułu ładującego, ale nie tego z klasy?
Hui Wang

1
świetnie, jestem tak głupi, że Object.class.getClassLoader();%20FileNotFoundException
używałem

5
@ycomp Ponieważ getResource zwraca adres URL, a nie plik. Metoda getFile pliku java.net.URL nie konwertuje adresu URL do pliku; po prostu zwraca ścieżkę i fragmenty adresu URL. Nie powinieneś nawet próbować konwertować go do pliku; po prostu zadzwoń do openStream i przeczytaj.
VGR

Sprawdź ten projekt, rozwiązuje skanowanie folderów zasobów: github.com/fraballi/resources-folder-scanner
Felix Aballi

60

Próbować:

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

IIRC getResourceAsStream()domyślnie odnosi się do pakietu klasy.

Jak zauważył @Terran, nie zapomnij dodać /na początku nazwy pliku


3
Dla tych, którzy szukają rozsądku, ten post prowadzi cię do zdobycia zasobu jako String stackoverflow.com/a/35446009/544045
Trevor

12
Klucz „/” jest kluczem.
Terran

33

Oto jedno szybkie rozwiązanie z użyciem 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);
}

Stosowanie:

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

28

Wypróbuj kody Flowing w projekcie Spring

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

Lub w projekcie innym niż wiosenny

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

Czy InputStream nie powinien być zamknięty?
030

7

Projekt nie wiosną:

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

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

W przypadku projektów wiosennych możesz również użyć jednego kodu wiersza, aby uzyskać dowolny plik w folderze zasobów:

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

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

5

Teraz ilustruję kod źródłowy do odczytu czcionki z katalogu zasobów utworzonych przez maven,

scr / main / resources / calibril.ttf

wprowadź opis zdjęcia tutaj

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

To zadziałało dla mnie i mam nadzieję, że cały kod źródłowy również ci pomoże, ciesz się!


5

Dla java po 1.7

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

Muszę użyć „/test.csv” (zwróć uwagę na ukośnik).
Leon,

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

Jeśli użyjesz kontekstowego narzędzia ClassLoader do znalezienia zasobu, na pewno będzie to kosztować wydajność aplikacji.


4
Programiści powinni zawsze martwić się wydajnością. Chociaż z pewnością należy unikać przedwczesnej optymalizacji, wiedza o bardziej skutecznym podejściu jest zawsze dobra. To tak, jakby znać różnicę między LinkedList a ArrayList i kiedy używać jednego lub drugiego.
Marvo

6
@Marvo: Programiści muszą zawsze martwić się jakością, możliwościami i łatwością konserwacji, wydajność stoi w kolejce.
Igor Rodriguez

2

Zaimportuj następujące elementy:

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

Następująca metoda zwraca plik z 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

Napotkałem ten sam problem .

Plik nie został znaleziony przez moduł ładujący klasy, co oznacza, że ​​nie został spakowany do artefaktu (słoika). Musisz zbudować projekt . Na przykład z maven:

mvn clean install

Tak więc pliki dodane do folderu zasobów przejdą do kompilacji maven i staną się dostępne dla aplikacji.

Chciałbym zachować swoją odpowiedź: nie wyjaśnia, jak czytać plik (inne odpowiedzi to wyjaśniają), odpowiada, dlaczego InputStream lub resourcebył zerowy . Podobna odpowiedź jest tutaj .


1
Dzięki, uratowałeś mnie od myślenia, że ​​tracę rozum!
StuPointerException

1

getResource () działał dobrze z plikami zasobów umieszczonymi src/main/resourcestylko w. Aby uzyskać plik, który znajduje się w innej ścieżce niż src/main/resourcespowiedz, src/test/javaże musisz go dokładnie utworzyć.

poniższy przykład może ci pomóc

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

Czy kod działa, gdy nie jest uruchamiany jar kompilacji Maven, na przykład podczas uruchamiania z IDE? Jeśli tak, upewnij się, że plik faktycznie znajduje się w słoiku. Folder zasobów powinien zostać zawarty w pliku pom, w <build><resources>.


Podczas używania środowiska Eclipse i uruchamiania kodu z samego IDE. Jak możemy ładować zasoby znajdujące się w „/ src / test / resources” w kodzie Java, szczególnie w testach jednostkowych. Rozważ standardową strukturę projektu maven.
Bhavesh

0

Poniższej klasy można użyć do załadowania pliku resourcez, classpatha także odebrania odpowiedniego komunikatu o błędzie w przypadku wystąpienia problemu z podanym 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

Rozwiązałem ten problem, dodając /scr/main/resourcesfolder do mojegoJava Build Path

wprowadź opis zdjęcia tutaj


spróbuj tego, ale to nie jest rozwiązanie
Jasonw

0

Mam to działa zarówno na działającym słoiku, jak i na IDE, pisząc jako

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

Jak wygląda twoja struktura plików?
luckydonald


0

Możesz użyć com.google.common.io.Resources.getResource, aby odczytać adres URL pliku, a następnie pobrać zawartość pliku za pomocą java.nio.file.Files, aby odczytać zawartość pliku.

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

-2

Sprawiam, że działa bez żadnego odniesienia do „class” lub „ClassLoader”.

Załóżmy, że mamy trzy scenariusze z lokalizacją pliku „example.file”, a katalog roboczy (w którym wykonuje się aplikacja) to home / mydocuments / program / projects / myapp:

a) Podfolder potomny katalogu roboczego: myapp / res / files / example.file

b) Podfolder niebędący potomkiem katalogu roboczego: projects / files / example.file

b2) Kolejny podfolder, który nie należy do katalogu roboczego: program / files / example.file

c) Folder główny: home / mydocuments / files / example.file (Linux; w Windows zamień home / na C :)

1) Wybierz właściwą ścieżkę: 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"

Zasadniczo, jeśli jest to folder główny, rozpocznij nazwę ścieżki od wiodącego ukośnika. Jeśli jest to podfolder, ukośnik nie może znajdować się przed nazwą ścieżki. Jeśli podfolder nie jest katalogiem podrzędnym do katalogu roboczego, musisz wykonać do niego cd za pomocą „../”. Informuje to system o przejściu o jeden folder w górę.

2) Utwórz obiekt File, podając właściwą ścieżkę:

File file = new File(path);

3) Teraz możesz już iść:

BufferedReader br = new BufferedReader(new FileReader(file));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.