Saya memuat file teks dari dalam sebuah paket di JAR yang dikompilasi dari proyek Java saya. Struktur direktori yang relevan adalah sebagai berikut:
/src/initialization/Lifepaths.txt
Kode saya memuat file dengan menelepon Class::getResourceAsStream
untuk mengembalikan a InputStream
.
public class Lifepaths {
public static void execute() {
System.out.println(Lifepaths.class.getClass().
getResourceAsStream("/initialization/Lifepaths.txt"));
}
private Lifepaths() {}
//This is temporary; will eventually be called from outside
public static void main(String[] args) {execute();}
}
Hasil cetak akan selalu dicetak null
, apa pun yang saya gunakan. Saya tidak yakin mengapa hal di atas tidak berhasil, jadi saya juga sudah mencoba:
"/src/initialization/Lifepaths.txt"
"initialization/Lifepaths.txt"
"Lifepaths.txt"
Tak satu pun dari ini bekerja. Saya telah membaca banyak pertanyaan sejauh ini tentang topik ini, tetapi tidak ada satupun yang membantu - biasanya, mereka hanya mengatakan untuk memuat file menggunakan path root, yang sudah saya lakukan. Itu, atau hanya memuat file dari direktori saat ini (hanya memuat filename
), yang saya juga coba. File sedang dikompilasi ke dalam JAR di lokasi yang sesuai dengan nama yang sesuai.
Bagaimana saya mengatasi ini?
Lifepaths.class
. Yang sedang berkata, mengapa itugetClassLoader()
memungkinkan untuk bekerja? (Juga, jangan ragu untuk mengirim jawaban!)Lifepaths.getClass()
? Tidak ada metode statis yang didefinisikan dalam Object ...getResource(String)
. BTW - Saya selalu memiliki masalah dalam membuat salah satu dari mereka bekerja dalamstatic
konteks. Masalahnya pada dasarnya bahwa kelas loader yang diperoleh adalah yang dimaksudkan untuk kelas J2SE. Anda perlu mendapatkan akses ke pemuat kelas konteks yang ditujukan untuk aplikasi itu sendiri.Jawaban:
Lifepaths.class.getClass().getResourceAsStream(...)
memuat sumber daya menggunakan pemuat kelas sistem, ini jelas gagal karena tidak melihat JAR AndaLifepaths.class.getResourceAsStream(...)
memuat sumber daya menggunakan loader kelas yang sama yang memuat kelas Lifepaths dan harus memiliki akses ke sumber daya di JAR Andasumber
/
sebelum path Anda jika file Anda berada di bawah direktori yang berbeda; misalnyainitialization/Lifepaths.txt
. Jika path file adalah sama dengan kelas Anda (tetapi di bawah sumber daya sebagai dir utama) Anda bisa meletakkan nama file tanpa/
. Sebagai contoh jika kelas Anda memiliki jalur berikutsrc/main/java/paths/Lifepaths.java
, file Anda harus memiliki jalur inisrc/main/resources/paths/Lifepaths.txt
.Aturannya adalah sebagai berikut:
Dan coba:
dari pada
(tidak yakin apakah itu membuat perbedaan, tetapi yang pertama akan menggunakan ClassLoader / JAR yang benar, sementara saya tidak yakin dengan yang terakhir)
sumber
Jadi ada beberapa cara untuk mendapatkan sumber daya dari toples dan masing-masing memiliki sintaks yang sedikit berbeda di mana jalur perlu ditentukan secara berbeda.
Penjelasan terbaik yang saya lihat adalah artikel ini dari JavaWorld . Saya akan meringkas di sini, tetapi jika Anda ingin tahu lebih banyak Anda harus memeriksa artikel.
Metode
1)
ClassLoader.getResourceAsStream()
.Format: "/" - nama yang dipisahkan; tidak ada penuntun "/" (semua nama adalah absolut).
Contoh:
this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
2)
Class.getResourceAsStream()
Format: "/" - nama yang dipisahkan; memimpin "/" menunjukkan nama absolut; semua nama lain relatif terhadap paket kelas
Contoh:
this.getClass().getResourceAsStream("/some/pkg/resource.properties");
sumber
Jangan gunakan jalur absolut, buatlah itu relatif terhadap direktori 'sumber daya' di proyek Anda. Kode cepat dan kotor yang menampilkan konten MyTest.txt dari direktori 'resources'.
sumber
Anda mungkin ingin mencoba ini untuk mendapatkan aliran yaitu pertama mendapatkan url dan kemudian membukanya sebagai aliran.
Saya pernah memiliki pertanyaan serupa: Membaca file txt dari jar gagal tetapi membaca gambar berhasil
sumber
Tampaknya ada masalah dengan ClassLoader yang Anda gunakan. Gunakan contextClassLoader untuk memuat kelas. Ini terlepas dari apakah itu dalam metode statis / non-statis
Thread.currentThread().getContextClassLoader().getResourceAsStream
......sumber
Saya menemukan diri saya dalam masalah serupa. Karena saya menggunakan maven, saya perlu memperbarui pom.xml saya untuk memasukkan sesuatu seperti ini:
Perhatikan tag sumber daya di sana untuk menentukan di mana folder itu berada. Jika Anda memiliki proyek bersarang (seperti saya lakukan) maka Anda mungkin ingin mendapatkan sumber daya dari daerah lain, bukan hanya dalam modul yang Anda kerjakan. Ini membantu mengurangi menyimpan file yang sama di setiap repo jika Anda menggunakan data konfigurasi yang sama
sumber
Apa yang berhasil bagi saya adalah menambahkan file di bawah
My Project/Java Resources/src
dan kemudian gunakanSaya tidak perlu menambahkan file ini secara eksplisit ke path (menambahkannya untuk
/src
melakukannya rupanya)sumber
Tidak tahu apakah bisa membantu, tetapi dalam kasus saya, saya memiliki sumber daya di folder / src / dan mendapatkan kesalahan ini. Saya kemudian memindahkan gambar ke folder bin dan itu memperbaiki masalah.
sumber
Pastikan direktori sumber daya Anda (misalnya "src") ada di classpath Anda (pastikan direktori sumber di path build Anda di gerhana).
Pastikan clazz diambil dari classloader utama.
Kemudian, untuk memuat src / inisialisasi / Lifepaths.txt, gunakan
Why:
clazz.getResourcesAsStream(foo)
mencari foo dari dalam classpath clazz , relatif terhadap direktori clazz tinggal . "/" Yang memimpin membuatnya memuat dari root direktori apa pun di classpath of clazz.Kecuali Anda berada dalam suatu wadah, seperti Tomcat, atau sedang melakukan sesuatu dengan ClassLoaders secara langsung, Anda bisa memperlakukan ecpathse / command line classpath sebagai satu-satunya classpath classpath.
sumber
Default JVM classloader akan menggunakan induk-classloader untuk memuat sumber pertama: .
Lifepaths.class.getClass()
classloader adalahbootstrap classloader
, jadigetResourceAsStream
akan mencari hanya $ JAVA_HOME, terlepas dari pengguna yang disediakanclasspath
. Jelas, Lifepaths.txt tidak ada di sana.Lifepaths.class
classloader adalahsystem classpath classloader
, jadigetResourceAsStream
akan mencari yang ditentukan penggunaclasspath
dan Lifepaths.txt ada di sana.Saat menggunakan
java.lang.Class#getResourceAsStream(String name)
, nama yang tidak dimulai dengan '/' akan ditambahkan denganpackage name
awalan. Jika Anda ingin menghindari ini, silakan gunakanjava.lang.ClassLoader#getResourceAsStream
. Sebagai contoh:sumber
Secara kasar:
getClass().getResource("/")
~ =Thread.currentThread().getContextClassLoader().getResource(".")
Misalkan struktur proyek Anda seperti berikut:
sumber
jika Anda menggunakan Maven, pastikan kemasan Anda adalah 'toples' bukan 'pom'.
sumber
Yang Anda butuhkan adalah classPath absolut penuh untuk file tersebut. Jadi alih-alih menebaknya, coba cari tahu ROOT dan kemudian pindahkan file ke basis file yang lebih baik <.war> struktur file ...
sumber
Apa yang berhasil bagi saya adalah saya meletakkan file di bawah
dan
sumber
src/main/JAVA
, jelas file non-kode Anda tidak boleh berada di sini.@Emracool ... Saya sarankan Anda alternatif. Karena Anda tampaknya mencoba memuat file * .txt. Lebih baik menggunakan
FileInputStream()
daripada inigetClass().getClassLoader().getResourceAsStream()
atau menjengkelkangetClass().getResourceAsStream()
. Setidaknya kode Anda akan dieksekusi dengan benar.sumber