Edited at

Javaで絶対パスを取得するgetAbsolutePath()の罠と解決方法

More than 3 years have passed since last update.


やりたいこと

Javaで相対パス(絶対パスでもOK)から絶対パスを取得したい

File#getAbsolutePath()を使うと期待通りの結果になりませんでした。

最終的には、以下のコードで期待通りの結果になりました。

(relativePathの型はString)

Paths.get(relativePath).toRealPath(LinkOption.NOFOLLOW_LINKS).toString()

どういう場合がうまくいかないのか、そしてその解決方法を書きたいと思います


カレントディレクトリ

以下のディレクトリがカレントディレクトリです

/Users/nwtgck/IdeaProjects/getCanonicalPath test/


getAbsolutePathでもOKな場合

以下のような相対パス("out/production")であれば、File#getAbsolutePath()でも期待通りの結果になります

relativePath = "out/production";

System.out.println(new File(relativePath).getAbsolutePath());


出力

/Users/nwtgck/IdeaProjects/getCanonicalPath test/out/production



getAbsolutePathの予想外1の結果

relativePath = "..";

System.out.println(new File(relativePath).getAbsolutePath());


出力

/Users/nwtgck/IdeaProjects/getCanonicalPath test/..


相対パスが「..」なので、出力が親ディレクトリの"/Users/nwtgck/IdeaProjects"になることを期待しましたが、なりません。


「..」で親ディレクトリの絶対パスを取得する

File#getgetCanonicalPath()を使うと期待通りに取得できます

relativePath = "..";

System.out.println(new File(relativePath).getCanonicalPath());


出力

/Users/nwtgck/IdeaProjects


基本的にはgetCanonicalPath()でOKですが、relativePathがシンボリックリンクの時はリンク先のパスになってしまいます。


シンボリックリンクでも絶対パスを取得する

relativePath = "/Users/nwtgck/Desktop/link";

System.out.println(Paths.get(relativePath).toRealPath(LinkOption.NOFOLLOW_LINKS));


出力

/Users/nwtgck/Desktop/link


シンボリックリンクでもそのファイル自体のパスになりました





  1. 仕様ですが、個人的には予想外でした