File.getAbsolutePath と getAbsoluteFile は相対でないパスを返す正しくないのですよ。ちょっとね。少なくとも、多くの人が考えている通りではありません。
パスの最初が絶対パスで、パスの残りの部分に相対パスの要素を指定してみましょう。
以下のコードではどのような結果を出すと思いますか?
実行してみると…public class Main { public static void main(String[] args) { try { File f = new File("/temp/../temp/../temp/../"); File abs = f.getAbsoluteFile(); File parent = abs.getParentFile(); System.out.println("Exists: " + f.exists()); System.out.println("Absolute Path: " + abs); System.out.println("FileName: " + abs.getName()); System.out.printf("The Parent Directory of %s is %s\n", abs, parent); System.out.printf("The CANONICAL Parent Directory of CANONICAL %s is %s\n", abs, abs.getCanonicalFile().getParent()); System.out.printf("The CANONICAL Parent Directory of ABSOLUTE %s is %s\n", abs, parent.getCanonicalFile()); System.out.println("Canonical Path: " + f.getCanonicalPath()); } catch (IOException ex) { System.out.println("Got an exception: " + ex); } } }
[訳注]Exists: true Absolute Path: D:\temp\..\temp\..\temp\.. FileName: .. The Parent Directory of D:\temp\..\temp\..\temp\.. is D:\temp\..\temp\..\temp The CANONICAL Parent Directory of CANONICAL D:\temp\..\temp\..\temp\.. is null The CANONICAL Parent Directory of ABSOLUTE D:\temp\..\temp\..\temp\.. is D:\temp Canonical Path: D:\
実行環境によってルートディレクトリは異なります。
d:\の親はd:\tempと言っていることに注目して下さい。ファイルfは実際にはルートディレクトリですので、本当なら親はnullになるはずです。私はようやくこのことがわかりました。getParentXXX()は単にパスの最後の部分を切り取るだけなのです。上記のような全く予期しない結果が簡単に出るのです。
実はこの振る舞いは、数年前にバグ登録しています。
http://bt2ws.central.sun.com/CrPrint?id=6687287
推奨策
(1) getAbsoluteではなく、getCanonicalを使うと、ファイルとカノニカルファイル名を1:1に対応します。つまり、各ファイルには唯一のカノニカルファイル名がありますが、ファイル名中のパス要素とは明確な関連がありません。各ファイルの絶対パスは無数に存在します。
(2) File fの親ファイルを取得するためには、getParentFile()を使わずに以下のような方法を使いましょう。
File parent = new File(f, "..");
原文はこちら。
http://blogs.oracle.com/foo/entry/tip_13_java_io_file
0 件のコメント:
コメントを投稿