Apa perbedaan antara Resource, URI, URL, Path, dan File di Java?

96

Saya sedang melihat sepotong kode Java sekarang, dan itu mengambil jalur sebagai String dan mendapatkan URL-nya menggunakan URL resource = ClassLoader.getSystemClassLoader().getResource(pathAsString);, lalu memanggil String path = resource.getPath()dan akhirnya dijalankan new File(path);.

Oh, dan ada juga panggilan ke URL url = resource.toURI();dan String file = resource.getFile().

Saya benar-benar bingung sekarang - kebanyakan karena terminologi, saya kira. Bisakah seseorang menjelaskan kepada saya perbedaannya, atau berikan beberapa tautan ke materi anti-tiruan? Terutama URI ke URL dan Resource to File ? Bagi saya, rasanya mereka harus menjadi hal yang sama, masing-masing ...

Perbedaan antara getFile()dan getPath()dijelaskan di sini: Apa perbedaan antara url.getFile () dan getpath ()? (Menariknya, mereka berdua tampaknya mengembalikan Strings, yang mungkin menambah banyak hal dalam pikiran saya ...)

Sekarang, jika saya memiliki locator yang mereferensikan kelas atau paket dalam file jar, akankah keduanya (yaitu jalur string file) berbeda?

resource.toString()akan memberi Anda jar:file:/C:/path/to/my.jar!/com/example/, setelah semua (perhatikan tanda seru).

Apakah perbedaan antara URI dan URL di Java yang sebelumnya tidak menyandikan spasi? Cf. File, URI, dan URL yang bentrok di Java (Jawaban ini menjelaskan perbedaan umum dan konseptual antara kedua istilah dengan cukup baik: URI mengidentifikasi dan URL menemukan; )

Terakhir - dan yang paling penting - mengapa saya membutuhkan Fileobjek; mengapa Resource ( URL) tidak cukup? (Dan apakah ada objek Resource?)

Maaf jika pertanyaan ini agak tidak teratur; itu hanya mencerminkan kebingungan yang saya miliki ... :)

Kristen
sumber
5
Dan Anda bahkan tidak mulai melihat Pathdan FileSystem dari NIO :)
eckes
2
@eckes Sakit kepala satu per satu, tolong. ;)
Christian
1
Nah dalam konteks pertanyaan Anda File / URL + URI tidak berhubungan. Yang satu adalah cara untuk memberi nama dan mengoperasikan file, yang lainnya adalah metode untuk memberi nama dan membaca dari sumber daya (yang bisa berupa file). Metode getFile dan getPath menangani komponen URL yang (secara membingungkan) dinamai seperti objek file. Sumber daya classloader tidak direpresentasikan sebagai file karena dapat memiliki asal yang berbeda (atau bersarang dalam file JAR).
eckes
1
Saya akan mencatat bahwa kode ini tidak mungkin berfungsi sebagaimana mestinya. Sebuah URLadalah buram - Anda menunjukkan itu jar:file:, yaitu sumber daya dalam .jararsip. Memukulnya menjadi Filesangat tidak mungkin menghasilkan sesuatu yang berguna.
Boris the Spider
1
Inti dari masalah Anda adalah kata resource dan path dapat memiliki arti yang berbeda, bergantung pada konteksnya.
Raedwald

Jawaban:

43

UPDATE 2017-04-12 Periksa jawaban JvR karena berisi penjelasan yang lebih lengkap dan tepat!


Harap dicatat bahwa saya tidak menganggap diri saya 100% kompeten untuk menjawab, namun berikut adalah beberapa komentar:

  • File mewakili file atau direktori yang dapat diakses melalui sistem file
  • resource adalah istilah umum untuk objek data yang dapat dimuat oleh aplikasi
    • biasanya sumber daya adalah file yang didistribusikan dengan aplikasi / perpustakaan dan dimuat melalui mekanisme pemuatan kelas (saat berada di jalur kelas)
  • URL#getPathadalah pengambil di bagian jalur URL ( protocol://host/path?query)
  • URL#getFile sesuai pengembalian JavaDoc path+query

Di Java, URIhanyalah sebuah struktur data untuk memanipulasi pengenal generik itu sendiri.

URLdi sisi lain benar-benar pencari sumber daya dan menawarkan fitur untuk benar-benar membaca sumber daya melalui URLStreamHandlers terdaftar .

URL dapat mengarah ke sumber daya sistem file dan Anda dapat membuat URL untuk setiap sumber daya sistem file dengan menggunakan file://protokol (karenanya hubungan File<-> URL).

Ketahuilah juga bahwa itu URL#getFiletidak ada hubungannya dengan java.io.File.


Mengapa saya membutuhkan objek File; mengapa Sumber Daya (URL) tidak cukup?

Cukup. Hanya jika Anda ingin meneruskan sumber daya ke beberapa komponen yang hanya dapat bekerja dengan file, Anda harus mendapatkannya File. Namun tidak semua URL sumber daya dapat diubah menjadi Files.

Dan apakah ada objek Resource?

Dari sudut pandang JRE, itu hanya istilah. Beberapa kerangka kerja memberi Anda kelas seperti itu (misalnya Sumber Daya Spring ).

Pavel Horal
sumber
5
Ada juga java.nio.file.Path, yang pada dasarnya merupakan pengganti (Java 7+) java.io.File, karena API yang terakhir tampaknya tidak dipikirkan dengan baik di masa-masa awal Java.
ntoskrnl
1
Umumnya, Anda harus meminimalkan penggunaan URL kecuali benar-benar diperlukan. Alasannya adalah bahwa metode sama dan hashCode URL diimplementasikan dengan cara yang mengejutkan: mereka memblokir panggilan metode.
kibibyte
3
@ Kibibyte: Saya berharap panggilan tersebut akan memblokir, untuk memiliki implementasi kode hash yang tidak sinkron dan sama sekarang, itu akan sangat mengganggu. Saya pikir yang Anda maksud adalah bahwa panggilan akan mencoba dan menyelesaikan host untuk menemukan apakah mereka setara dan dengan demikian berpotensi melakukan pemblokiran panggilan jaringan.
Newtopian
52

Saya benar-benar bingung sekarang - kebanyakan karena terminologi, saya kira. Bisakah seseorang menjelaskan kepada saya perbedaannya, atau berikan beberapa tautan ke materi anti-tiruan? Terutama URI ke URL dan Resource to File? Bagi saya, rasanya mereka harus sama, masing-masing ...

Terminologi ini membingungkan dan terkadang membingungkan, dan sebagian besar lahir dari evolusi Java sebagai API dan platform seiring waktu. Untuk memahami bagaimana istilah-istilah ini berarti apa yang mereka lakukan, penting untuk mengenali dua hal yang memengaruhi desain Java:

  • Kompatibilitas mundur. Aplikasi lama harus berjalan pada instalasi yang lebih baru, idealnya tanpa modifikasi. Ini berarti bahwa API lama (dengan nama dan terminologinya) perlu dipertahankan melalui semua versi yang lebih baru.
  • Lintas platform. API harus menyediakan abstraksi yang dapat digunakan dari platform yang mendasarinya, apakah itu sistem operasi atau browser.

Saya akan menjelaskan konsep dan bagaimana mereka muncul. Saya akan menjawab pertanyaan Anda yang lain, pertanyaan spesifik setelah itu, karena saya mungkin harus mengacu pada sesuatu di bagian pertama.

Apa itu "Sumber Daya"?

Sepotong data abstrak dan generik yang dapat ditemukan dan dibaca. Secara longgar dikatakan, Java menggunakan ini untuk merujuk ke "file" yang mungkin bukan file tetapi mewakili bagian data bernama. Itu tidak memiliki kelas langsung atau representasi antarmuka di Java , tetapi karena propertinya (dapat ditemukan, dapat dibaca) sering diwakili oleh URL.

Karena salah satu tujuan desain awal Java adalah untuk dijalankan di dalam browser, sebagai aplikasi kotak pasir (applet!) Dengan hak / hak istimewa / izin keamanan yang sangat terbatas, Java membuat perbedaan yang jelas (teoretis) antara file (sesuatu di lokal). sistem file) dan sumber daya (sesuatu yang perlu dibaca). Inilah sebabnya mengapa membaca sesuatu yang berhubungan dengan aplikasi (ikon, file kelas, dan sebagainya) dilakukan melalui ClassLoader.getResourcedan bukan melalui kelas File.

Sayangnya, karena "resource" juga merupakan istilah umum yang berguna di luar interpretasi ini, ia juga digunakan untuk menamai hal-hal yang sangat spesifik (misalnya class ResourceBundle , UIResource , Resource ) yang dalam pengertian ini bukan merupakan resource.

Kelas utama yang mewakili (jalur ke) sumber daya adalah java.nio.file.Path , java.io.File , java.net.URI , dan java.net.URL .

File (java.io, 1.0)

Representasi abstrak dari nama jalur file dan direktori.

Kelas File mewakili sumber daya yang dapat dijangkau melalui sistem file asli platform . Ini hanya berisi nama file, jadi ini lebih merupakan jalur (lihat nanti) yang ditafsirkan platform host sesuai dengan pengaturan, aturan, dan sintaksnya sendiri.

Perhatikan bahwa File tidak perlu menunjuk ke sesuatu yang lokal , hanya sesuatu yang dipahami oleh platform host dalam konteks akses file, misalnya jalur UNC di Windows. Jika Anda memasang file ZIP sebagai sistem file di OS Anda, maka File akan membaca entri yang ada di dalamnya dengan baik.

URL (java.net, 1.0)

URL Kelas mewakili Uniform Resource Locator, penunjuk ke "sumber daya" di World Wide Web. Sumber daya dapat berupa sesuatu yang sederhana seperti file atau direktori, atau dapat menjadi referensi ke objek yang lebih rumit, seperti kueri ke database atau ke mesin pencari.

Bersamaan dengan konsep sumber daya, URL merepresentasikan sumber daya tersebut dengan cara yang sama saat kelas File merepresentasikan file di platform host: sebagai string terstruktur yang mengarah ke sumber daya. URL juga berisi skema yang memberi petunjuk tentang cara menjangkau sumber daya (dengan "file:" menjadi "tanyakan platform host"), dan memungkinkan untuk menunjuk sumber daya melalui HTTP, FTP, di dalam JAR, dan yang lainnya.

Sayangnya, URL datang dengan sintaks dan terminologinya sendiri, termasuk penggunaan "file" dan "path". Jika URL adalah file-URL, URL.getFile akan mengembalikan string yang identik dengan string jalur dari file yang direferensikan.

Class.getResource mengembalikan URL: lebih fleksibel daripada mengembalikan File, dan telah melayani kebutuhan sistem seperti yang dibayangkan di awal 1990-an.

URI (java.net, 1.4)

Merepresentasikan referensi Uniform Resource Identifier (URI).

URI adalah abstraksi (sedikit) atas URL. Perbedaan antara URI dan URL bersifat konseptual dan sebagian besar bersifat akademis, tetapi URI lebih baik didefinisikan dalam pengertian formal, dan mencakup kasus penggunaan yang lebih luas. Karena URL dan URI adalah / bukan hal yang sama, kelas baru diperkenalkan untuk mewakilinya, dengan metode URI.toURL dan URL.toURI untuk berpindah antara satu dan lainnya.

Di Java, perbedaan utama antara URL dan URI adalah bahwa URL memiliki ekspektasi dapat diselesaikan , sesuatu yang mungkin diinginkan aplikasi dari InputStream; URI diperlakukan lebih seperti thingamajig abstrak yang mungkin mengarah ke sesuatu yang dapat diselesaikan (dan biasanya memang demikian), tetapi apa artinya dan cara mencapainya lebih terbuka untuk konteks dan interpretasi.

Jalur (java.nio.file, 1.7)

Objek yang dapat digunakan untuk mencari file di sistem file. Ini biasanya akan mewakili jalur file yang bergantung pada sistem.

File API baru, yang diikonkan dalam antarmuka Path, memungkinkan fleksibilitas yang jauh lebih besar daripada yang dapat ditawarkan kelas File. Antarmuka Path adalah abstraksi dari kelas File , dan merupakan bagian dari New IO File API . Jika File selalu menunjuk ke "file" sebagaimana dipahami oleh platform host, Path lebih umum: Path mewakili file (sumber daya) dalam sistem file arbitrer .

Path menghilangkan ketergantungan pada konsep platform host dari sebuah file. Ini bisa berupa entri dalam file ZIP, file yang dapat dijangkau melalui FTP atau SSH-FS, representasi multi-root dari jalur kelas aplikasi, atau apa pun yang dapat direpresentasikan secara bermakna melalui antarmuka FileSystem dan drivernya, FileSystemProvider. Ini membawa kekuatan sistem file "pemasangan" ke dalam konteks aplikasi Java.

Platform host direpresentasikan melalui "sistem file default"; saat Anda menelepon File.toPath, Anda mendapatkan Path pada sistem file default.


Sekarang, jika saya memiliki locator yang mereferensikan kelas atau paket dalam file jar, akankah keduanya (yaitu jalur string file) berbeda?

Tidak sepertinya. Jika file jar ada di sistem file lokal, Anda tidak boleh memiliki komponen kueri, jadi URL.getPathdan URL.getFileharus mengembalikan hasil yang sama. Namun, pilih yang Anda butuhkan: file-URL mungkin biasanya tidak memiliki komponen kueri, tapi saya yakin bisa menambahkannya.

Terakhir - dan yang paling penting - mengapa saya membutuhkan objek File; mengapa Sumber Daya (URL) tidak cukup?

URL mungkin tidak cukup karena File memberi Anda akses ke data housekeeping seperti izin (dapat dibaca, ditulis, dieksekusi), jenis file (apakah saya adalah direktori?), Dan kemampuan untuk mencari dan memanipulasi sistem file lokal. Jika ini adalah fitur yang Anda butuhkan, File atau Path menyediakannya.

Anda tidak memerlukan File jika Anda memiliki akses ke Path. Beberapa API lama mungkin memerlukan File.

(Dan apakah ada objek Resource?)

Tidak, tidak ada. Ada banyak hal yang dinamai seperti itu, tetapi itu bukan sumber daya dalam arti ClassLoader.getResource.

JvR
sumber
Wow, teliti sekali. Hanya melalui itu, tetapi sudah memiliki pertanyaan tindak lanjut pertama: Ketika Anda mengatakan File "hanya berisi nama file", tidakkah Anda bertentangan dengan pernyataan awal Anda bahwa itu "Representasi abstrak dari nama path file dan direktori" - iemore?
Kristen
1
@Christian Maksud saya "hanya nama" seperti dalam: tidak dengan cara apapun memodelkan isi file; itu hanya pembungkus tipis di sekitar tali. Bagian "representasi abstrak" dikutip dari dokumen API. ;)
JvR
Jawaban ini layak mendapatkan lebih banyak suara positif ... akan memperbarui jawaban saya yang diterima untuk mengarahkan pembaca ke yang satu ini.
Pavel Horal
12

Jawaban Pavel Horal bagus.

Seperti yang dia katakan, kata "file" memiliki arti yang sama sekali berbeda (secara praktis tidak berhubungan) dalam URL#getFilevs java.io.File- mungkin itu bagian dari kebingungan.

Hanya untuk menambahkan:

  • Sebuah sumber daya di Jawa adalah sebuah konsep abstrak, sumber data yang dapat dibaca. Lokasi (atau alamat) sumber daya diwakili di Jawa oleh sebuah URLobjek.

  • Sebuah sumber daya dapat sesuai dengan file biasa dalam filesystem lokal (khususnya, ketika yang URLdimulai dengan file://). Tetapi sumber daya lebih umum (bisa juga beberapa file yang disimpan dalam jar, atau beberapa data untuk dibaca dari jaringan, atau dari memori, atau ...). Dan itu juga lebih terbatas, karena a File(selain hal lain selain file biasa: direktori, link) juga dapat dibuat dan ditulis.

  • Ingat di Java, Fileobjek tidak benar-benar mewakili "file" tetapi lokasi (nama lengkap, dengan jalur) dari file. Jadi, Fileobjek memungkinkan Anda untuk mencari (dan membuka) file, sebagai URLmemungkinkan Anda untuk mengakses (dan membuka) sumber daya. (Tidak ada Resourcekelas di Java untuk mewakili sumber daya, tetapi tidak ada kelas yang mewakili file! Sekali lagi: Filebukan file, ini adalah jalur file).

leonbloy.dll
sumber
3

Seperti yang saya pahami, Anda dapat mengategorikannya sebagai berikut:

Berbasis Web: URI dan URL.

  • URL: URL adalah lokasi tertentu di internt (hanya alamat web biasa seperti - stackoverflow.com)
  • URI: Ever URL adalah URI. Tapi URI juga bisa berisi hal-hal seperti "mailto:", jadi URI juga bisa disebut "script".

Dan lokal: Resource, Path, dan Files

  • Resource: Resource adalah file di dalam jar Anda. Mereka digunakan untuk memuat file dari toples / container.
  • Path: Path pada dasarnya adalah string. Tapi itu datang dengan beberapa fungsi praktis untuk menggabungkan banyak string, atau menambahkan file ke string. Itu memastikan jalur yang Anda bangun valid.
  • File: Ini adalah referensi ke direktori atau file. Ini digunakan untuk mengubah file, membukanya, dll.

Akan lebih mudah jika mereka digabungkan menjadi satu kelas - sangat membingungkan: D

Saya harap ini membantu Anda :)

(Saya baru saja melihat-lihat dokumentasinya - lihat docs.oracle.com)

Cyphrags
sumber
0

File adalah representasi abstrak dari suatu entitas di sistem file lokal.

Path umumnya berupa string yang menunjukkan lokasi file dalam sistem file. Biasanya tidak menyertakan nama file. Jadi c: \ documents \ mystuff \ stuff.txt akan memiliki path dengan nilai "C: \ documents \ mystuff" Jelas sekali format nama file dan path absolut akan sangat bervariasi dari sistem file ke sistem file.

URL adalah kumpulan URI dengan URL biasanya mewakili sumber daya yang dapat diakses melalui http. Saya rasa tidak ada aturan ketat tentang kapan sesuatu harus berupa URI vs URL. URI adalah string dalam bentuk "protocol: // resource-identifier" seperti bitcoin: // params, http://something.com?param=value . Kelas-kelas seperti URL umumnya membungkus string dan menyediakan metode utilitas yang tidak memiliki alasan untuk diberikan oleh String.

Tidak ada yang namanya Resource, setidaknya tidak dalam arti yang Anda bicarakan. Hanya karena sebuah metode bernama getResource tidak berarti ia mengembalikan objek bertipe Resource.

Pada akhirnya, cara terbaik untuk mencari tahu apa yang dilakukan metode Class adalah membuat instance-nya di kode Anda, memanggil metode tersebut, lalu melangkah dalam mode debug atau mengirimkan hasilnya ke System.out.

Jim W.
sumber
Definisi Anda tentang "jalur" TIDAK sesuai dengan konsep "jalur" dalam konteks OP
leonbloy