Javaのリソース、URI、URL、パス、ファイルの違いは何ですか?


95

現在Javaコードの一部を調べています。パスは文字列として取得され、そのURLはを使用して取得されURL resource = ClassLoader.getSystemClassLoader().getResource(pathAsString);、次にが呼び出されString path = resource.getPath()、最後に実行されnew File(path);ます。

あ、そしてとへの呼び出しもURL url = resource.toURI();ありString file = resource.getFile()ます。

私は今完全に混乱しています-専門用語のせいだと思います。誰かが違いを教えてくれますか、それともダミープルーフ素材へのリンクをいくつか提供してくれますか?特にURLへのURIとファイルへのリソース?私には、それぞれ同じものであるように感じます...

違いgetFile()とは、getPath()ここで説明されていますurl.getFile()とGETPATH()の違いは何ですか?(興味深いことに、どちらも文字列を返すようです。おそらく私の心の状態に大きな影響を与えます...)

さて、jarファイル内のクラスまたはパッケージを参照するロケーターがある場合、これら2つ(つまり、ファイル文字列のパス)は異なりますか?

resource.toString()あなたを与えるだろうjar:file:/C:/path/to/my.jar!/com/example/(感嘆符に注意してください)すべての後に、。

JavaのURIURLの 違いは、前者がスペースをエンコードしないことですか?Cf. Javaで競合するファイル、URI、およびURL(この回答は、2つの用語の一般的な概念の違いをかなりよく説明しています:URIが特定し、URLが特定します;

最後に、そして最も重要なこととして、なぜFileオブジェクトが必要URLなのリソース()が十分でないのはなぜですか?(そしてResourceオブジェクトはありますか?)

この質問が少し整理されていなければ申し訳ありません。それは私が持っている混乱を反映しています... :)


5
そしてPath、NIOからFileSystem を見始めることさえしなかった:)
15年

2
@eckes一度に一つの頭痛をお願いします。;)
クリスチャン

1
よくあなたの質問のコンテキストでFile / URL + URIは関連していません。1つはファイルに名前を付けて操作する手段であり、もう1つはファイルに名前を付けてリソースから読み取る方法です。getFileメソッドとgetPathメソッドは、ファイルオブジェクトのように(紛らわしく)名前が付けられているURLのコンポーネントを処理します。クラスローダーリソースは、オリジンが異なる(またはJARファイルにネストされる)可能性があるため、ファイルとして表されません。
15年

1
このコードが意図したとおりに機能する可能性は低いことに注意してください。URLある不透明な -あなたはそれがのショーとしてjar:file:すなわち内のリソース、.jarアーカイブ。これをaに叩き込んFileでも、有用な結果が得られる可能性はほとんどありません。
Boris the Spider

1
問題の核心は、「リソース」と「パス」という単語は、コンテキストに応じて異なる意味を持つ可能性があるということです。
Raedwald、2015年

回答:


43

更新2017-04-12 JvRの回答には、より網羅的で正確な説明が含まれているため、確認してください!


私は自分が100%回答できるとは思っていませんが、それでもここにいくつかのコメントがあります:

  • File ファイルシステムを介してアクセス可能なファイルまたはディレクトリを表します
  • リソースは、アプリケーションがロードできるデータオブジェクトの総称です。
    • 通常、リソースは、アプリケーション/ライブラリと共に配布され、クラスロードメカニズムを介してロードされるファイルです(クラスパスにある場合)
  • URL#getPathURLのパス部分のゲッターです(protocol://host/path?query
  • URL#getFile JavaDocが返すように path+query

JavaではURI、一般的な識別子自体を操作するための単なるデータ構造です。

URL一方、実際にはリソースロケータであり、登録されたを介してリソースを実際に読み取る機能を提供しますURLStreamHandler

URLはファイルシステムリソースにつながる可能性があり、file://プロトコル(したがってFile<-> URL関係)を使用してすべてのファイルシステムリソースのURLを構築できます。

また、とURL#getFileは無関係であることにも注意してくださいjava.io.File


なぜFileオブジェクトが必要なのですか。リソース(URL)が十分でないのはなぜですか?

十分です。ファイルでのみ機能するコンポーネントにリソースを渡したい場合のみ、そこから取得する必要がありますFile。ただし、すべてのリソースURLをに変換できるわけではありませんFile

そして、Resourceオブジェクトはありますか?

JREの観点からは、それは単なる用語です。一部のフレームワークは、そのようなクラスを提供します(例:SpringのResource)。


5
また、Javaの初期の頃には後者のAPIは十分に考えられていなかったjava.nio.file.Pathためjava.io.File、基本的には(Java 7+)の代わりとなるもあります。
ntoskrnl 2015年

1
一般に、絶対に必要でない限り、URLの使用を最小限に抑える必要があります。その理由は、URLのequalsおよびhashCodeメソッドが驚くべき方法で実装されているためです。これらはメソッド呼び出しをブロックしています。
キビバイト2015年

3
@kibibyte:呼び出しがブロックされ、ハッシュコードとが非同期で実装されることを期待しますが、これは非常に不安になります。私が言ったことは、呼び出しがホストを解決しようとしてホストを解決し、それらが同等であるかどうかを調べて、ブロッキングネットワーク呼び出しを行う可能性があるということです。
2016年

50

私は今完全に混乱しています-専門用語のせいだと思います。誰かが違いを教えてくれますか、それともダミープルーフ素材へのリンクをいくつか提供してくれますか?特にURLへのURIとファイルへのリソース?私には、それぞれ同じものであるように感じます...

用語は紛らわしく、時には混乱を招き、ほとんどがJavaのAPIとしての進化と、プラットフォームとしての進化の両方から生まれました。これらの用語が何を意味するのかを理解するには、Javaの設計に影響を与える2つのことを認識することが重要です。

  • 下位互換性。 古いアプリケーションは、理想的には変更せずに、新しいインストールで実行する必要があります。つまり、すべての新しいバージョンで古いAPI(名前と用語を含む)を維持する必要があります。
  • クロスプラットフォーム。 APIは、オペレーティングシステムであれブラウザであれ、基盤となるプラットフォームの使用可能な抽象化を提供する必要があります。

コンセプトとそれらがどのようになってきたのかについて説明します。最初の部分で何かを参照する必要があるかもしれないので、その後、他の特定の質問に答えます。

「リソース」とは何ですか?

検索して読み取ることができる抽象的な一般的なデータ。 大まかに言って、Javaはこれを使用して、ファイルではないが名前付きのデータを表す「ファイル」を参照します。 Javaは直接のクラスまたはインターフェース表現はありませんが、そのプロパティ(配置可能、読み取り可能)のため、URLで表されることがよくあります。

Javaの初期の設計目標の1つはブラウザー内で実行され、サンドボックスアプリケーション(アプレット!)として非常に制限された権限/特権/セキュリティクリアランスを備えていたため、Javaはファイル(ローカル上の何か)ファイルシステム)およびリソース(読み取る必要があるもの)。 これが、アプリケーションに関連するもの(アイコン、クラスファイルなど)の読み取りClassLoader.getResourceがFileクラスではなく、Fileクラスを通じて行われる理由です。

残念ながら、「リソース」もこの解釈のでは有用な一般的な用語であるため、この意味ではリソースではない非常に具体的なもの(例:ResourceBundleUIResourceResource)の名前にも使用されます。

リソース(へのパス)を表す主なクラスは、java.nio.file.Pathjava.io.Filejava.net.URI、およびjava.net.URLです。

ファイル(java.io、1.0)

ファイルとディレクトリのパス名の抽象的な表現。

Fileクラスは、プラットフォームのネイティブファイルシステムを介して到達可能なリソースを表します。これにはファイルの名前のみが含まれるため、実際には、ホストプラットフォームが独自の設定、ルール、および構文に従って解釈するパス(後述)になります。

Fileはローカルなものを指す必要はなく、ホストプラットフォームがファイルアクセスのコンテキストで理解できるもの(WindowsのUNCパスなど)を指す必要があることに注意してください。OSのファイルシステムとしてZIPファイルをマウントすると、Fileは含まれているエントリを正常に読み取ります。

URL(java.net、1.0)

クラスURLは、World Wide Web上の「リソース」へのポインタであるUniform Resource Locatorを表します。リソースは、ファイルやディレクトリなどの単純なものにすることも、データベースや検索エンジンへのクエリなど、より複雑なオブジェクトへの参照にすることもできます。

リソースの概念と並行して、URLはFileクラスがホストプラットフォームのファイルを表すのと同じ方法でそのリソースを表します。リソースを指す構造化文字列として URLには、リソースへのアクセス方法を示すスキーム(「file:」は「ホストプラットフォームに尋ねる」)が含まれているため、HTTP、FTP、JAR内などでリソースを指すことができます。

残念ながら、URLには、「ファイル」や「パス」の使用など、独自の構文と用語が付属しています。URLがファイルURLの場合、URL.getFileは参照ファイルのパス文字列と同じ文字列を返します。

Class.getResource URLを返します。これはFileを返すよりも柔軟性が高く、1990年代初頭に想像されたように、システムのニーズに対応しています。

URI(java.net、1.4)

Uniform Resource Identifier(URI)参照を表します。

URIは、URLの(わずかな)抽象化です。 URIとURLの違いは概念的でほとんどが学術的なものですが、URIは正式な意味でより適切に定義されており、幅広いユースケースをカバーしています。URLとURIは同じではないため、それらを表す新しいクラスが導入され、メソッドURI.toURLとURL.toURIが相互に移動します。

Javaでは、URLとURIの主な違いは、URLが解決可能であるという期待を伝えていることです。AN URIは、より抽象的なthingamajigのように扱われるかもしれない何かで解決を指し、(通常)が、その意味とどのようにそれは文脈や解釈により開かれて到達すること。

パス(java.nio.file、1.7)

ファイルシステム内のファイルを見つけるために使用できるオブジェクト。通常、システムに依存するファイルパスを表します。

Pathインターフェースでアイコン化された新しいファイルAPIは、Fileクラスが提供できるよりもはるかに高い柔軟性を可能にします。PathインターフェースはFileクラスを抽象化したもので、New IO File APIの一部です。Fileがホストプラットフォームによって理解される「ファイル」を必ず指す場合、Pathはより一般です。任意のファイルシステム内のファイル(リソース)を表します。

パスは、ホストプラットフォームのファイルの概念への依存を取り除きます。これは、ZIPファイルのエントリ、FTPまたはSSH-FSを介して到達可能なファイル、アプリケーションのクラスパスのマルチルート表現、またはFileSystemインターフェースとそのドライバーであるFileSystemProviderを介して意味のあるものを表すことができるものであれば何でもかまいません。これは、ファイルシステムを「マウント」する能力をJavaアプリケーションのコンテキストにもたらします。

ホストプラットフォームは「デフォルトのファイルシステム」で表されます。を呼び出すとFile.toPath、デフォルトのファイルシステムのパスが取得されます。


さて、jarファイル内のクラスまたはパッケージを参照するロケーターがある場合、これら2つ(つまり、ファイル文字列のパス)は異なりますか?

ありそうもない。jarファイルは、ローカルファイルシステム上にある場合は、クエリコンポーネントを持つべきではない、そうURL.getPathURL.getFile同じ結果を返す必要があります。ただし、必要なものを選択します。ファイルURLには通常クエリコンポーネントがない場合がありますが、とにかく1つ追加することができます。

最後に、そして最も重要なこととして、なぜFileオブジェクトが必要なのでしょうか。リソース(URL)が十分でないのはなぜですか?

Fileでは、アクセス許可(読み取り、書き込み、実行可能)、ファイルタイプ(ディレクトリかどうか)、ローカルファイルシステムを検索および操作する機能などのハウスキーピングデータにアクセスできるため、URLでは不十分な場合があります。これらが必要な機能である場合、ファイルまたはパスがそれらを提供します。

パスにアクセスできる場合は、ファイルは必要ありません。ただし、一部の古いAPIではファイルが必要になる場合があります。

(そしてResourceオブジェクトはありますか?)

いいえ、ありません。そのように命名されたものはたくさんありますが、それらはの意味でのリソースではありませんClassLoader.getResource


うわー、非常に徹底しています。ちょうどそれを通過しますが、すでに最初のフォローアップの質問があります:ファイルに「ファイルの名前のみが含まれている」と言うとき、それが「ファイルとディレクトリのパス名の抽象的な表現」であるという最初のステートメントと矛盾しないでください-すなわち?
クリスチャン

1
@クリスチャン私は「名前だけ」を意味しました。ファイルの内容をモデル化するものではありません。それは単にストリングを包む薄いラッパーです。「抽象表現」の部分は、APIドキュメントから引用されています。;)
JvR 2016年

この答えはもっと多くの賛成票を持つに値します...読者にこれを示すように私の受け入れられた答えを更新します。
Pavel Horal 2017

12

Pavel Horalの答えはいいです。

彼が言うように、「ファイル」という言葉はURL#getFilevsで 完全に異なる(実際には無関係)意味を持っていますjava.io.File-それは混乱の一部かもしれません。

追加するだけです:

  • Java の リソースは抽象的な概念であり、読み取ることができるデータのソースです。リソースの場所(またはアドレス)は、JavaではURLオブジェクトによって表されます。

  • リソースは、ローカルファイルシステム(ITSは、具体的には、ときに通常のファイルに対応することができるURLことから始まりますfile://)。しかし、リソースはより一般的です(jarに格納されているファイル、ネットワークから、またはメモリから読み取られるデータなど)。また、File(通常のファイル以外のものであることに加えて、ディレクトリ、リンク)も作成して書き込むことができるため、さらに制限されます。

  • Javaでは、Fileオブジェクトは実際には「ファイル」を表すのではなく、ファイルの場所(パスを含む完全な名前)を思い出してください。したがって、Fileオブジェクトを使用するとURL、リソースにアクセス(およびオープン)できるのと同様に、ファイルを特定(およびオープン)できます。(ResourceJavaにはリソースを表すクラスはありませんが、ファイルを表すクラスはありません!もう一度:Fileファイルではなく、ファイルのパスです)。


3

それらを理解しているので、次のように分類できます。

Webベース:URIとURL。

  • URL:URLはインターネット上の明確な場所です(例:-stackoverflow.comのような通常のWebアドレス)
  • URI:これまでのURLはURIです。しかし、URIには「mailto:」のようなものを含めることもできるので、URIも、まさしく「スクリプト」のようなものです。

そしてローカル:リソース、パス、ファイル

  • リソース:リソースはjar内のファイルです。これらは、jar /コンテナーからファイルをロードするために使用されます。
  • パス:パスは基本的に文字列です。ただし、複数の文字列を連結したり、ファイルを文字列に追加するための便利な関数がいくつか付属しています。作成しているパスが有効であることを確認します。
  • ファイル:これはディレクトリまたはファイルへの参照です。ファイルの変更、ファイルのオープンなどに使用されます。

それらが1つのクラスにマージされると、より簡単になります-それらは本当に混乱します:D

これがあなたのお役に立てば幸いです:)

(私はドキュメントを見てみました-docs.oracle.comを見てください)


0

ファイルは、ローカルファイルシステム内のエンティティの抽象的な表現です。

パスは通常、ファイルシステム内のファイルの場所を示す文字列です。通常、ファイル名は含まれません。したがって、c:\ documents \ mystuff \ stuff.txtのパスは "C:\ documents \ mystuff"の値になります。明らかに、絶対ファイル名とパスの形式は、ファイルシステムによって大きく異なります。

URLはURIのsusbsetであり、URLは通常、http経由でアクセス可能なリソースを表します。私は何かがURI対URLでなければならない時についてのどんな種類の鉄則もないと思います。URIは、bitcoin:// params、http://something.com param = valueのような「protocol:// resource-identifier」の形式の文字列です。URLのようなクラスは通常、文字列をラップし、文字列が提供する理由がないユーティリティメソッドを提供します。

少なくともあなたが話している意味では、Resourceのようなものはありません。メソッドにgetResourceという名前が付いているからといって、Resourceタイプのオブジェクトを返すわけではありません。

クラスのメソッドが何をするかを理解するための最終的に最良の方法は、コード内でクラスのインスタンスを作成し、メソッドを呼び出して、デバッグモードでステップスルーするか、結果をSystem.outに送信することです。


「パス」の定義は、OPコンテキストの「パス」の概念に対応していません
leonbloy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.