JavaでのgetPath()、getAbsolutePath()、およびgetCanonicalPath()の比較
1. 概要
java.io.Fileクラスには、ファイルシステムパスを取得するための3つのメソッド(getPath()、getAbsolutePath()、およびgetCanonicalPath())があります。
この記事では、それらの違いを簡単に見て、一方を他方よりも使用することを選択できるユースケースについて説明します。
2. メソッドの定義と例
まず、3つのメソッドの定義と、ユーザーのホームディレクトリに次のディレクトリ構造が存在することに基づく例について説明します。
|-- example
|-- example.txt
|-- foo
| |-- foo-one.txt
| \-- foo-two.txt
\-- bar
|-- bar-one.txt
|-- bar-two.txt
\-- baz
|-- baz-one.txt
\-- baz-two.txt
2.1. getPath()
簡単に言えば、getPath()は、ファイルの抽象パス名のString表現を返します。 これは本質的にthe pathname passed to the File constructorです。
したがって、Fileオブジェクトが相対パスを使用して作成された場合、getPath()メソッドからの戻り値も相対パスになります。
\{user.home}/exampleディレクトリから次のコードを呼び出す場合:
File file = new File("foo/foo-one.txt");
String path = file.getPath();
path変数の値は次のとおりです。
foo/foo-one.txt // on Unix systems
foo\foo-one.txt // on Windows systems
Windowsシステムでは、名前区切り文字がコンストラクターに渡されたスラッシュ(/)文字からバックスラッシュ(\)文字に変更されていることに注意してください。 これは、the returned String always uses the platform’s default name-separator characterが原因です。
2.2. getAbsolutePath()
getAbsolutePath()メソッドはthe pathname of the file after resolving the path for the current user directoryを返します—これは絶対パス名と呼ばれます。 したがって、前の例では、file.getAbsolutePath()は次を返します。
/home/username/example/foo/foo-one.txt // on Unix systems
C:\Users\username\example\foo\foo-one.txt // on Windows systems
このメソッドは、相対パスの現在のディレクトリのみを解決します。 省略表現(「.”」や「..”」など)はこれ以上解決されません。 したがって、ディレクトリ\{user.home}/example:から次のコードを実行すると
File file = new File("bar/baz/../bar-one.txt");
String path = file.getAbsolutePath();
変数pathの値は次のようになります。
/home/username/example/bar/baz/../bar-one.txt // on Unix systems
C:\Users\username\example\bar\baz\..\bar-one.txt // on Windows systems
2.3. getCanonicalPath()
getCanonicalPath()メソッドはさらに一歩進んで、ディレクトリ構造に従ってresolves the absolute pathname as well as the shorthands or redundant names like “.” and “..“を実行します。 また、Unixシステムではresolves symbolic links、Windowsシステムではconverts the drive letter to a standard caseです。
したがって、前の例では、getCanonicalPath()メソッドは次を返します。
/home/username/example/bar/bar-one.txt // on Unix systems
C:\Users\username\example\bar\bar-one.txt // on Windows systems
別の例を見てみましょう。 現在のディレクトリを$\{user.home}/exampleおよびパラメータnew File(“bar/baz/./baz-one.txt”)を使用して作成されたFileオブジェクトとして指定すると、getCanonicalPath()の出力は次のようになります。
/home/username/example/bar/baz/baz-one.txt // on Unix systems
C:\Users\username\example\bar\baz\baz-one.txt // on Windows Systems
省略表現を使用する方法は無数にあるため、ファイルシステム上の1つのファイルに無数の絶対パスを含めることができることに注意してください。 ただし、そのような表現はすべて解決されるため、the canonical path will always be unique。
最後の2つの方法とは異なり、getCanonicalPath()はファイルシステムクエリを必要とするため、IOExceptionをスローする可能性があります。
たとえば、Windowsシステムでは、不正な文字の1つを使用してFileオブジェクトを作成すると、正規パスを解決するとIOExceptionがスローされます。
new File("*").getCanonicalPath();
3. 使用事例
Fileオブジェクトをパラメーターとして受け取り、そのfully qualified nameをデータベースに保存するメソッドを作成しているとしましょう。 パスが相対的なものなのか、速記が含まれているのかはわかりません。 この場合、getCanonicalPath()を使用することをお勧めします。
ただし、getCanonicalPath()はファイルシステムを読み取るため、パフォーマンスが低下します。 冗長な名前やシンボリックリンクがなく、ドライブ文字の大文字と小文字が標準化されている場合(Windows OSを使用している場合)、getAbsoultePath()を使用することをお勧めします。
4. 結論
このクイックチュートリアルでは、ファイルシステムパスを取得するための3つのFileメソッドの違いについて説明しました。 また、ある方法が他の方法よりも好まれるユースケースも示しました。
この記事の例を示すJunitテストクラスはover on GitHubにあります。