Saya memiliki kode ini yang membaca semua file dari direktori.
File textFolder = new File("text_directory");
File [] texFiles = textFolder.listFiles( new FileFilter() {
public boolean accept( File file ) {
return file.getName().endsWith(".txt");
}
});
Ini bekerja dengan baik. Ini mengisi array dengan semua file yang diakhiri dengan ".txt" dari direktori "text_directory".
Bagaimana saya bisa membaca isi direktori dengan cara yang sama di dalam file JAR?
Jadi yang benar-benar ingin saya lakukan adalah, mencantumkan semua gambar di dalam file JAR saya, sehingga saya dapat memuatnya dengan:
ImageIO.read(this.getClass().getResource("CompanyLogo.png"));
(Yang itu berfungsi karena "CompanyLogo" adalah "hardcode" tetapi jumlah gambar di dalam file JAR bisa dari 10 hingga 200 panjang variabel.)
EDIT
Jadi saya kira masalah utama saya adalah: Bagaimana cara mengetahui nama file JAR dimana kelas utama saya tinggal?
Memang saya bisa membacanya menggunakan java.util.Zip
.
Struktur saya seperti ini:
Mereka seperti:
my.jar!/Main.class
my.jar!/Aux.class
my.jar!/Other.class
my.jar!/images/image01.png
my.jar!/images/image02a.png
my.jar!/images/imwge034.png
my.jar!/images/imagAe01q.png
my.jar!/META-INF/manifest
Sekarang saya bisa memuat misalnya "images / image01.png" menggunakan:
ImageIO.read(this.getClass().getResource("images/image01.png));
Tapi hanya karena saya tahu nama filenya, selebihnya saya harus memuatnya secara dinamis.
Jawaban:
Perhatikan bahwa di Java 7, Anda dapat membuat
FileSystem
dari file JAR (zip), lalu menggunakan mekanisme berjalan dan pemfilteran direktori NIO untuk mencarinya. Ini akan mempermudah penulisan kode yang menangani JAR dan direktori "meledak".sumber
Kode yang berfungsi untuk file IDE dan .jar:
sumber
FileSystems.newFileSystem()
mengambilMap<String, ?>
, jadi Anda perlu menentukan untukCollections.emptyMap()
itu perlu mengembalikan yang diketik sesuai. Ini bekerja:Collections.<String, Object>emptyMap()
.fileSystem
!walk
metodeFiles
hanya tersedia di 1.8). Satu-satunya masalah adalah direktori sumber daya muncul diFiles.walk(myPath, 1)
, bukan hanya di file. Saya kira elemen pertama dapat diabaikan begitu sajamyPath = fileSystem.getPath("/resources");
tidak bekerja untuk saya; itu tidak menemukan apa pun. Seharusnya "gambar" dalam kasus saya dan "gambar" -direktori sudah pasti termasuk dalam toples saya!jawaban erickson bekerja dengan sempurna:
Inilah kode kerja.
Dan saya baru saja mengubah metode pemuatan saya dari ini:
Untuk ini:
sumber
Saya ingin memperluas jawaban acheron55 , karena ini adalah solusi yang sangat tidak aman, karena beberapa alasan:
FileSystem
objek.FileSystem
objek sudah ada.Ini adalah solusi yang lebih aman:
Tidak perlu melakukan sinkronisasi melalui nama file; seseorang dapat dengan mudah melakukan sinkronisasi pada objek yang sama setiap saat (atau membuat metode
synchronized
), ini murni pengoptimalan.Saya akan mengatakan bahwa ini masih merupakan solusi yang bermasalah, karena mungkin ada bagian lain dalam kode yang menggunakan
FileSystem
antarmuka di atas file yang sama, dan itu dapat mengganggu mereka (bahkan dalam satu aplikasi berulir).Juga, itu tidak memeriksa
null
s (misalnya, padagetClass().getResource()
.Antarmuka Java NIO khusus ini agak mengerikan, karena ia memperkenalkan sumber daya non-thread-safe global / tunggal, dan dokumentasinya sangat kabur (banyak yang tidak diketahui karena implementasi khusus penyedia). Hasil dapat berbeda untuk
FileSystem
penyedia lain (bukan JAR). Mungkin ada alasan bagus untuk itu; Saya tidak tahu, saya belum meneliti implementasinya.sumber
Dengan asumsi bahwa proyek Anda dikemas dalam Jar (tidak harus benar!), Anda dapat menggunakan ClassLoader.getResource () atau findResource () dengan nama kelas (diikuti oleh .class) untuk mendapatkan jar yang berisi kelas tertentu. Anda harus mengurai nama jar dari URL yang dikembalikan (tidak terlalu sulit), yang akan saya tinggalkan sebagai latihan untuk pembaca :-)
Pastikan untuk menguji kasus yang kelasnya bukan bagian dari toples.
sumber
CodeSource
.Saya telah mentransfer jawaban acheron55 ke Java 7 dan menutup
FileSystem
objek. Kode ini bekerja di IDE, di file jar dan di jar di dalam perang melawan Tomcat 7; tetapi perhatikan bahwa itu tidak berfungsi di stoples di dalam perang terhadap JBoss 7 (itu memberiFileSystemNotFoundException: Provider "vfs" not installed
, lihat juga posting ini ). Selain itu, seperti kode aslinya, ini bukan thread safe, seperti yang disarankan oleh errr . Untuk alasan ini saya telah meninggalkan solusi ini; namun, jika Anda dapat menerima masalah ini, berikut adalah kode siap pakai saya:sumber
Berikut adalah metode yang saya tulis untuk "menjalankan semua JUnits di bawah paket". Anda harus bisa menyesuaikannya dengan kebutuhan Anda.
Edit: Ah, dalam hal ini, Anda mungkin menginginkan cuplikan ini juga (kasus penggunaan yang sama :))
sumber
Berikut adalah contoh penggunaan pustaka Refleksi untuk memindai jalur kelas secara rekursif dengan pola nama regex yang ditambah dengan beberapa fasilitas Guava untuk mengambil konten sumber daya:
Ini bekerja dengan toples dan kelas yang meledak.
sumber
File jar hanyalah file zip dengan manifes terstruktur. Anda dapat membuka file jar dengan alat java zip biasa dan memindai isi file dengan cara itu, memompa aliran, dll. Kemudian menggunakannya dalam panggilan getResourceAsStream, dan itu harus semua keren dory.
EDIT / setelah klarifikasi
Saya butuh satu menit untuk mengingat semua bagian dan saya yakin ada cara yang lebih bersih untuk melakukannya, tetapi saya ingin melihat bahwa saya tidak gila. Dalam proyek saya image.jpg adalah file di beberapa bagian dari file jar utama. Saya mendapatkan pemuat kelas dari kelas utama (SomeClass adalah titik masuk) dan menggunakannya untuk menemukan sumber daya image.jpg. Kemudian beberapa keajaiban aliran untuk memasukkannya ke dalam hal ImageInputStream ini dan semuanya baik-baik saja.
sumber
new File("blah.JAR")
untuk membuat objek File yang mewakili JAR, misalnya. Cukup ganti "blah.JAR" dengan nama JAR Anda.Diberikan file JAR yang sebenarnya, Anda dapat membuat daftar isinya menggunakan
JarFile.entries()
. Anda perlu mengetahui lokasi file JAR - Anda tidak bisa hanya meminta classloader untuk mencantumkan semua yang bisa didapatnya.Anda harus dapat menentukan lokasi file JAR berdasarkan URL yang dikembalikan dari
ThisClassName.class.getResource("ThisClassName.class")
, tetapi ini mungkin sedikit rumit.sumber
new File("baz.jar)
, objek File akan mewakili file JAR Anda.Beberapa waktu lalu saya membuat sebuah fungsi yang mendapat classess dari dalam JAR:
sumber
sumber
Ada dua utilitas yang sangat berguna yang disebut JarScan:
www.inetfeedback.com/jarscan
jarscan.dev.java.net
Lihat juga pertanyaan ini: JarScan, pindai semua file JAR di semua subfolder untuk kelas tertentu
sumber
Mekanisme paling kuat untuk mencantumkan semua resource di classpath saat ini menggunakan pola ini dengan ClassGraph , karena pola ini menangani larik mekanisme spesifikasi classpath seluas mungkin , termasuk sistem modul JPMS yang baru. (Saya adalah penulis ClassGraph.)
Ada banyak cara lain untuk menangani sumber daya juga.
sumber
Hanya cara yang berbeda untuk mendaftar / membaca file dari URL jar dan melakukannya secara rekursif untuk toples bersarang
https://gist.github.com/trung/2cd90faab7f75b3bcbaa
sumber
Satu lagi untuk jalan:
Ini sedikit lebih fleksibel untuk mencocokkan nama file tertentu karena menggunakan penggabungan karakter pengganti.
Gaya yang lebih fungsional:
sumber