Bagaimana cara memuat file dari folder sumber daya?

240

Proyek saya memiliki struktur berikut:

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

Saya memiliki file /src/test/resources/test.csvdan saya ingin memuat file dari unit test di/src/test/java/MyTest.java

Saya memiliki kode ini yang tidak berfungsi. Itu mengeluh "Tidak ada file atau direktori".

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

Saya juga mencoba ini

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

Ini juga tidak berfungsi. Ia kembali null. Saya menggunakan Maven untuk membangun proyek saya.

codereviewanskquestions
sumber
Tidak berhasil bagaimana? Apa kesalahanmu
Daniel Kaplan
17
coba inithis.getClass().getResource("/test.csv")
SRy
@SRy itu berhasil (karena ini akan memberikan url jalur absolut sebagai balasan) namun saat saya membuat file jar itu tidak berfungsi karena di dalam jar dan path absolut menjadi tidak valid, apakah ada cara untuk bermain dengan jalur relatif itu sendiri
ShankMungkin

Jawaban:

240

Coba yang berikutnya:

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

Jika hal di atas tidak berhasil, berbagai proyek telah ditambahkan kelas berikut: 1 (kode di sini ). 2ClassLoaderUtil

Berikut adalah beberapa contoh bagaimana kelas itu digunakan:

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
}

Catatan

  1. Lihat di The Wayback Machine .
  2. Juga di GitHub .
Paul Vargas
sumber
14
Terima kasih untuk jawabannya, dapatkah Anda menjelaskan mengapa kami harus menggunakan loader yang sangat spesifik ini tetapi tidak untuk kelas itu?
Hui Wang
1
hebat, saya sangat bodoh bahwa saya menggunakan Object.class.getClassLoader();, dari konteks statis yang tidak bekerja - saran ini tidak - baik hampir, itu menyuntikkan %20ruang yang memberi sayaFileNotFoundException
ycomp
5
@comp Karena getResource mengembalikan URL, bukan file. Metode getFile dari java.net.URL tidak mengonversi URL ke file; itu hanya mengembalikan jalur dan bagian permintaan URL. Anda bahkan tidak boleh mencoba mengubahnya menjadi File; panggil saja openStream dan baca itu.
VGR
Periksa proyek ini, selesaikan
Felix Aballi
60

Mencoba:

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

IIRC getResourceAsStream()secara default relatif terhadap paket kelas.

Seperti yang dicatat oleh @Terran, jangan lupa menambahkan /di awal nama file

vanza
sumber
3
Bagi mereka yang mencari kewarasan, pos ini memberi Anda semua cara untuk mendapatkan sumber daya sebagai String stackoverflow.com/a/35446009/544045
Trevor
12
"/" Adalah kuncinya.
Terran
33

Berikut adalah satu solusi cepat dengan penggunaan Jambu Biji :

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

Pemakaian:

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

Coba kode Mengalir pada proyek Musim Semi

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

Atau pada proyek non musim semi

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);
srsajid
sumber
Haruskah InputStream tidak ditutup?
030
7

Proyek non musim semi:

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

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

Untuk proyek semi, Anda juga dapat menggunakan satu kode baris untuk mendapatkan file apa pun di bawah folder sumber daya:

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

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

Sekarang saya menggambarkan kode sumber untuk membaca font dari direktori sumber daya pakar,

scr / main / resources / calibril.ttf

masukkan deskripsi gambar di sini

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

Itu bekerja untuk saya dan berharap bahwa seluruh kode sumber juga akan membantu Anda, Selamat Menikmati!

ArifMustafa
sumber
5

Untuk java setelah 1.7

 List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));
phray2002
sumber
Saya harus menggunakan "/ test.csv" (perhatikan slash).
Leon
4
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

Jika Anda menggunakan ClassLoader konteks untuk menemukan sumber daya maka pasti akan biaya kinerja aplikasi.

Bimales Mandal
sumber
4
Programmer harus selalu memperhatikan kinerja. Meskipun optimasi prematur tentu saja harus dihindari, mengetahui pendekatan yang lebih efisien untuk diambil selalu baik. Ini seperti mengetahui perbedaan antara LinkedList dan ArrayList dan kapan harus menggunakan satu atau yang lainnya.
Marvo
6
@ Marvo: Programmer harus selalu memperhatikan kualitas, kemampuan dan kemudahan pemeliharaan, kinerja ada di antrian.
Igor Rodriguez
2

Impor yang berikut ini:

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

Metode berikut mengembalikan file dalam 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
sumber
2

Saya menghadapi masalah yang sama .

File tidak ditemukan oleh pemuat kelas, yang berarti tidak dikemas ke dalam artefak (tabung). Anda perlu membangun proyek . Misalnya, dengan pakar:

mvn clean install

Jadi file yang Anda tambahkan ke folder sumber daya akan masuk ke pakar pembuatan dan menjadi tersedia untuk aplikasi.

Saya ingin menjaga jawaban saya: tidak menjelaskan cara membaca file (jawaban lain lakukan menjelaskan bahwa), itu menjawab mengapa InputStream atau resourceitu nol . Jawaban serupa ada di sini .

Yan Khonski
sumber
1
Terima kasih, menyelamatkan saya dari pemikiran bahwa saya kehilangan akal!
StuPointerException
1

getResource () berfungsi dengan baik dengan file sumber daya ditempatkan di src/main/resourceshanya. Untuk mendapatkan file yang berada di jalur selain src/main/resourcesmengatakan src/test/javaAnda harus membuatnya dengan rumit.

contoh berikut dapat membantu Anda

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

Apakah kode berfungsi saat tidak menjalankan toples Maven-build, misalnya saat menjalankan dari IDE Anda? Jika demikian, pastikan file tersebut benar-benar termasuk dalam toples. Folder sumber daya harus dimasukkan dalam file pom, di <build><resources>.

Jorn
sumber
Saat menggunakan gerhana dan menjalankan kode dari IDE itu sendiri. Bagaimana kita memuat sumber daya yang terletak di "/ src / test / resources" dalam kode Java khususnya dalam pengujian unit. Pertimbangkan struktur proyek pakar standar.
Bhavesh
0

Kelas berikut dapat digunakan untuk memuat resourcedari classpathdan juga menerima pesan kesalahan pas jika ada masalah dengan yang diberikan 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
sumber
0

Saya memecahkan masalah ini dengan menambahkan /scr/main/resourcesfolder ke file sayaJava Build Path

masukkan deskripsi gambar di sini

sklimkovitch
sumber
coba ini tapi ini bukan solusinya
Jasonw
0

Saya membuatnya bekerja pada kedua jar berjalan dan dalam IDE dengan menulis sebagai

 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
sumber
Bagaimana struktur file Anda?
luckydonald
0
this.getClass().getClassLoader().getResource("filename").getPath()
shiva kumar
sumber
0

Anda dapat menggunakan com.google.common.io.Resources.getResource untuk membaca url file dan kemudian mendapatkan konten file menggunakan java.nio.file.Files untuk membaca konten file.

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

Saya membuatnya bekerja tanpa referensi ke "class" atau "ClassLoader".

Katakanlah kita memiliki tiga skenario dengan lokasi file 'example.file' dan direktori kerja Anda (tempat aplikasi Anda dijalankan) adalah home / mydocuments / program / proyek / myapp:

a) Sub folder yang turun ke direktori kerja: myapp / res / files / example.file

b) Sub folder tidak turun ke direktori kerja: proyek / file / example.file

b2) Sub folder lain yang tidak turun ke direktori kerja: program / file / example.file

c) Folder root: home / mydocuments / files / example.file (Linux; di Windows ganti home / dengan C :)

1) Dapatkan jalan yang benar: 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"

Pada dasarnya, jika itu adalah folder root, mulailah nama path dengan slash terkemuka. Jika ini adalah sub folder, tidak boleh ada garis miring sebelum nama path. Jika sub folder tidak turun ke direktori kerja Anda harus cd ke sana menggunakan "../". Ini memberitahu sistem untuk naik satu folder.

2) Buat objek File dengan melewati jalan yang benar:

File file = new File(path);

3) Sekarang Anda baik untuk pergi:

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