I'm loading file teks dari dalam sebuah paket yang dihimpun JAR Java saya proyek. Terkait struktur direktori adalah sebagai berikut:
/src/initialization/Lifepaths.txt
Kode yang digunakan untuk memuat file adalah:
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();}
}
Print out akan selalu mencetak null
, tidak peduli apa yang saya gunakan. I'm tidak yakin mengapa hal di atas tidak't bekerja, jadi saya've juga mencoba:
"/src/inisialisasi/Lifepaths.txt"
"inisialisasi/Lifepaths.txt"
"Lifepaths.txt"
Ini tidak bekerja. I've baca akses pertanyaan jadi jauh mengenai topik ini, tapi tidak satupun dari mereka telah membantu - biasanya, mereka hanya mengatakan untuk memuat file menggunakan root path, yang saya'm sudah lakukan. Itu, atau hanya memuat file dari direktori saat ini (hanya memuat filename
), yang saya've juga mencoba. Berkas yang dikumpulkan ke dalam BOTOL di lokasi yang sesuai dengan nama yang sesuai.
Bagaimana saya memecahkan masalah ini?
Lifepaths.kelas.getClass().getResourceAsStream(...)
beban sumber daya menggunakan sistem kelas loader, itu jelas gagal karena tidak melihat anda Guci
Lifepaths.kelas.getResourceAsStream(...)
beban menggunakan sumber daya yang sama kelas loader yang dimuat Lifepaths kelas dan harus memiliki akses ke sumber daya di Guci
Aturan adalah sebagai berikut:
Dan mencoba:
Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")
bukan
Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")
(tidak yakin apakah itu membuat perbedaan, namun mantan akan menggunakan yang benar ClassLoader/ JAR, sementara aku'm tidak yakin dengan yang terakhir)
Jadi ada beberapa cara untuk mendapatkan sumber daya dari botol dan masing-masing memiliki sedikit sintaks yang berbeda di mana jalan harus ditentukan secara berbeda.
Penjelasan terbaik yang saya telah melihat ini adalah artikel dari JavaWorld. I'll meringkas di sini, tapi jika anda ingin tahu lebih banyak anda harus check out artikel ini.
Metode
ClassLoader.getResourceAsStream()
. Format: "/" dipisahkan dengan nama; no terkemuka "/" (semua nama-nama yang mutlak).
Contoh: ini.getClass().getClassLoader().getResourceAsStream("beberapa/pkg/sumber daya.sifat");
Kelas.getResourceAsStream()
Format: "/" dipisahkan dengan nama; terkemuka "/" menunjukkan mutlak nama; semua nama-nama lain yang relatif terhadap kelas's paket
Contoh: ini.getClass().getResourceAsStream("/beberapa/pkg/sumber daya.sifat");
Don't menggunakan absolute path, membuat mereka relatif ke 'sumber daya' direktori proyek anda. Cepat dan kotor kode yang menampilkan isi dari MyTest.txt dari direktori 'sumber daya'.
@Test
public void testDefaultResource() {
// can we see default resources
BufferedInputStream result = (BufferedInputStream)
Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
byte [] b = new byte[256];
int val = 0;
String txt = null;
do {
try {
val = result.read(b);
if (val > 0) {
txt += new String(b, 0, val);
}
} catch (IOException e) {
e.printStackTrace();
}
} while (val > -1);
System.out.println(txt);
}
Anda mungkin ingin mencoba ini untuk mendapatkan stream saya.e pertama mendapatkan url dan kemudian membukanya sebagai aliran.
URL url = getClass().getResource("/initialization/Lifepaths.txt");
InputStream strm = url.openStream();
Saya pernah punya pertanyaan serupa: https://stackoverflow.com/questions/16563622/reading-txt-file-from-jar-fails-but-reading-image-works/16564611#16564611
Tampaknya ada masalah dengan ClassLoader yang anda gunakan. Gunakan contextClassLoader untuk memuat kelas. Hal ini terlepas dari apakah itu adalah dalam statis/non-statis metode
Benang.currentThread().getContextClassLoader().getResourceAsStream
......
Saya menemukan diri saya dalam masalah serupa. Sejak saya menggunakan maven yang saya butuhkan untuk update saya pom.xml untuk memasukkan sesuatu seperti ini:
...
</dependencies>
<build>
<resources>
<resource>
<directory>/src/main/resources</directory>
</resource>
<resource>
<directory>../src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
...
Catatan sumber daya tag di sana untuk menentukan dimana folder tersebut. Jika anda telah bersarang proyek (seperti yang saya lakukan) maka anda mungkin ingin untuk mendapatkan sumber daya dari daerah lain, bukan hanya dalam modul anda bekerja di. Hal ini membantu mengurangi menjaga file yang sama di masing-masing repo jika anda menggunakan yang sama config data
Pastikan direktori sumber daya (misalnya "src") berada dalam classpath anda (pastikan itu's sumber direktori dalam membangun jalan di eclipse).
Pastikan clazz dimuat dari classloader.
Kemudian, untuk beban src/initialization/Lifepaths.txt, menggunakan
clazz.getResourceAsStream("/initialization/Lifepaths.txt");
Mengapa:
clazz.getResourcesAsStream(foo)
terlihat dari foo dalam classpath dari clazz, relatif ke direktori clazz tinggal di. Terkemuka "/" membuat beban dari root direktori di classpath dari clazz.
Kecuali anda're dalam sebuah wadah dari beberapa jenis, seperti Tomcat, atau melakukan sesuatu dengan ClassLoaders secara langsung, anda hanya bisa memperlakukan anda eclipse/command line classpath sebagai satu-satunya classloader classpath.
Secara kasar:
getClass().getResource("/")
~= Benang.currentThread().getContextClassLoader().getResource(".")
Misalkan struktur proyek anda adalah seperti berikut:
`` ├── src │ ├── utama │ └── tes │ └── tes │ ├── jawa │ │ └── com │ │ └── github │ │ └── xyz │ │ └── proj │ │ ├── MainTest.java │ │ └── TestBase.java │ └── sumber daya │ └── abcd.txt └── target └── tes-kelas ├── com └── abcd.txt
``
`` // di MainClass.java ini.getClass.getResource("/") -> "~/proj_dir/target/tes-kelas/" ini.getClass.getResource(".") -> "~/proj_dir/target/tes-kelas/com/github/xyz/proj/" Benang.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/tes-kelas/" Benang.currentThread().getContextClassLoader().getResources("/") -> null
``
Apa yang bekerja untuk saya adalah untuk menambahkan file di bawah Proyek Saya/Jawa Resources/src dan kemudian menggunakan
this.getClass().getClassLoader().getResourceAsStream(myfile.txt);
Aku't perlu explicity tambahkan file ini ke jalan (menambahkannya ke /src apakah itu rupanya)
Default JVM classloader akan menggunakan orang tua-classloader untuk memuat sumber-sumber pertama: .
Lifepaths.kelas.getClass()
's classloader adalah bootstrap classloader
, jadi getResourceAsStream
akan mencari $JAVA_HOME saja, terlepas dari pengguna disediakan classpath
. Jelas, Lifepaths.txt tidak ada.
Lifepaths.class
's classloader adalah sistem classpath classloader
, jadi getResourceAsStream
akan mencari user-defined classpath
dan Lifepaths.txt ada.
Ketika menggunakan jawa.lang.Kelas#getResourceAsStream(String nama)
, nama yang tidak mulai dengan '/' akan ditambahkan dengan nama paket
sebagai awalan. Jika anda ingin menghindari hal ini, silakan menggunakan jawa.lang.ClassLoader#getResourceAsStream
.
Misalnya:
Jawa ClassLoader loader = Benang.currentThread().getContextClassLoader(); String resourceName = "Lifepaths.txt"; InputStream resourceStream = loader.getResourceAsStream(resourceName);
@Emracool... saya'd sarankan anda alternatif. Karena anda tampaknya akan mencoba untuk memuat *.file txt. Lebih baik menggunakan FileInputStream()
ketimbang ini mengganggu getClass().getClassLoader().getResourceAsStream()
atau getClass().getResourceAsStream()
. Setidaknya kode anda akan mengeksekusi dengan baik.