Apakah ada API untuk mendapatkan sumber daya classpath (misalnya apa yang akan saya dapatkan Class.getResource(String)
) sebagai java.nio.file.Path
? Idealnya, saya ingin menggunakan Path
API baru yang mewah dengan sumber daya classpath.
143
Paths.get(URI)
, lalu ´URL.toURI (), and last
getResource () `yang mengembalikan aURL
. Anda mungkin bisa mengikatnya bersama. Belum mencoba.Jawaban:
Yang ini bekerja untuk saya:
sumber
Thread.currentThread().getContextClassLoader().getResource(resourceName).toURI()
Menebak apa yang ingin Anda lakukan, adalah panggilan Files.lines (...) pada sumber yang berasal dari classpath - mungkin dari dalam toples.
Karena Oracle berbelit-belit ketika Path adalah Path dengan tidak membuat getResource mengembalikan path yang dapat digunakan jika berada di file jar, yang perlu Anda lakukan adalah sesuatu seperti ini:
sumber
class.getResource
membutuhkan garis miring tetapigetSystemResourceAsStream
tidak dapat menemukan file ketika diawali dengan garis miring.Solusi paling umum adalah sebagai berikut:
Kendala utama adalah untuk menangani dua kemungkinan, baik, memiliki sistem file yang sudah ada yang harus kita gunakan, tetapi tidak menutup (seperti dengan
file
URI atau penyimpanan modul Java 9), atau harus membuka dan dengan demikian dengan aman menutup sistem file sendiri (seperti file zip / jar).Oleh karena itu, solusi di atas merangkum tindakan aktual dalam
interface
, menangani kedua kasus, dengan aman menutup setelahnya dalam kasus kedua, dan bekerja dari Java 7 ke Java 10. Ini menyelidiki apakah sudah ada filesystem terbuka sebelum membuka yang baru, sehingga juga berfungsi jika komponen lain dari aplikasi Anda telah membuka sistem file untuk file zip / jar yang sama.Itu dapat digunakan di semua versi Java yang disebutkan di atas, misalnya untuk membuat daftar isi suatu paket (
java.lang
dalam contoh) sebagaiPath
s, seperti ini:Dengan Java 8 atau lebih baru, Anda dapat menggunakan ekspresi lambda atau referensi metode untuk mewakili tindakan aktual, misalnya
untuk melakukan hal yang sama.
Rilis terakhir sistem modul Java 9 telah memecahkan contoh kode di atas. JRE tidak konsisten mengembalikan jalan
/java.base/java/lang/Object.class
untukObject.class.getResource("Object.class")
sementara itu harus/modules/java.base/java/lang/Object.class
. Ini dapat diperbaiki dengan menambahkan sebelumnya yang hilang/modules/
ketika jalur induk dilaporkan sebagai tidak ada:Kemudian, itu akan kembali berfungsi dengan semua versi dan metode penyimpanan.
sumber
Ternyata Anda dapat melakukan ini, dengan bantuan penyedia Sistem File Zip bawaan . Namun, melewatkan URI sumber daya secara langsung ke
Paths.get
tidak akan berhasil; sebagai gantinya, pertama-tama seseorang harus membuat sistem file zip untuk toples URI tanpa nama entri, kemudian merujuk ke entri dalam sistem file itu:Memperbarui:
Sudah ditunjukkan dengan benar bahwa kode di atas mengandung kebocoran sumber daya, karena kode membuka objek FileSystem baru tetapi tidak pernah menutupnya. Pendekatan terbaik adalah dengan melewatkan objek pekerja yang mirip konsumen, seperti halnya jawaban Holger melakukannya. Buka ZipFS FileSystem cukup lama bagi pekerja untuk melakukan apa pun yang perlu dilakukan dengan Path (selama pekerja tidak mencoba untuk menyimpan objek Path untuk digunakan nanti), kemudian tutup FileSystem.
sumber
newFileSystem
dapat menyebabkan banyak sumber daya nongkrong terbuka selamanya. Meskipun addendum @raisercostin menghindari kesalahan saat mencoba membuat sistem file yang sudah dibuat, jika Anda mencoba menggunakan yang dikembalikanPath
Anda akan mendapatkanClosedFileSystemException
. @ Tanggapan Holger bekerja dengan baik untuk saya.FileSystem
. Jika Anda memuat sumber daya dari Jar, dan Anda kemudian membuat yang diperlukanFileSystem
-FileSystem
itu juga akan memungkinkan Anda untuk memuat sumber daya lainnya dari Jar yang sama. Juga, setelah Anda membuat yang baru,FileSystem
Anda bisa mencoba memuat sumber daya lagi menggunakanPaths.get(Path)
dan implementasi akan secara otomatis menggunakan yang baruFileSystem
.#getPath(String)
metode padaFileSystem
objek.Saya menulis metode pembantu kecil untuk membaca
Paths
dari sumber daya kelas Anda. Ini cukup mudah digunakan karena hanya membutuhkan referensi kelas yang telah Anda simpan sumber daya Anda serta nama sumber daya itu sendiri.sumber
Anda tidak dapat membuat URI dari sumber daya di dalam file jar. Anda cukup menulisnya ke file temp dan kemudian menggunakannya (java8):
sumber
Baca File dari folder sumber daya menggunakan NIO, di java8
sumber
Anda perlu mendefinisikan Filesystem untuk membaca sumber daya dari file jar seperti yang disebutkan di https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html . Saya berhasil membaca sumber daya dari file jar dengan kode di bawah ini:
sumber