44

DirectoryWalker クラスで、File インスタンスが実際にディレクトリへのシンボリック リンクであるかどうかを確認したいと考えています (ウォーカーが UNIX システム上を歩くと仮定します)。インスタンスがディレクトリであることは既にわかっていますが、シンボリック リンクを特定するための信頼できる条件は次のとおりでしょうか?

File file;
// ...      
if (file.getAbsolutePath().equals(file.getCanonicalPath())) {
    // real directory ---> do normal stuff      
}
else {
    // possible symbolic link ---> do link stuff
}
4

7 に答える 7

49

Apache Commons で使用されている手法では、ファイル自体ではなく、親ディレクトリへの標準パスが使用されます。不一致の原因がシンボリック リンクであることを保証できるとは思いませんが、ファイルに特別な処理が必要であることを示す良い兆候です。

これはコンパクトにするために変更されたApache コード(ライセンスの対象) です。

public static boolean isSymlink(File file) throws IOException {
  if (file == null)
    throw new NullPointerException("File must not be null");
  File canon;
  if (file.getParent() == null) {
    canon = file;
  } else {
    File canonDir = file.getParentFile().getCanonicalFile();
    canon = new File(canonDir, file.getName());
  }
  return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
}
于 2009-05-01T23:41:45.640 に答える
15

Java 1.6 は、ファイル システムへのそのような低レベルのアクセスを提供しません。Java 1.7 に含まれるはずの NIO 2 では、シンボリック リンクがサポートされるようです新しい API のドラフトが利用可能です。そこにはシンボリックリンクが記載されており、それらを作成してフォローすることが可能です。ファイルがシンボリック リンクかどうかを調べるためにどの方法を使用すればよいか、正確にはわかりません。NIO 2 について議論するためのメーリング リストがあります。

于 2009-05-01T23:36:20.770 に答える
14

また、解決されたファイルに基づいて結果が返されることに注意してください。したがって、ターゲットが存在しないシンボリックリンクを参照している場合はfile.isFile()file.isDirectory()両方が返されます。falsefile

(これ自体は有用な答えではないことはわかっていますが、何度かつまずいたので、共有する必要があると思いました)

于 2011-10-11T17:06:59.383 に答える
5

getCanonicalPath()絶対パスとは異なる可能性のある他のことを実行できるようです。

このメソッドは、最初に必要に応じて、getAbsolutePath() メソッドを呼び出したかのように、このパス名を絶対形式に変換してから、システムに依存する方法で一意の形式にマップします。これには通常、「.」などの冗長な名前を削除することが含まれます。およびパス名からの「..」、シンボリック リンクの解決 (UNIX プラットフォームの場合)、およびドライブ文字の標準ケースへの変換 (Microsoft Windows プラットフォームの場合)。

しかし、ユースケースの大部分ではうまくいくかもしれません。あなたのマイレージは異なる場合があります。

于 2009-05-01T23:39:48.360 に答える
3

*nix 専用のコードをすでに作成している場合は、次のように Java からシェル コマンドを実行できます。

Process p = Runtime.getRuntime().exec(new String[]{"test", "-h", yourFileName});
p.waitFor();
if (p.exitValue() == 0) 
   System.out.println("This file is a symbolic link");
else
   System.out.println("This file is not a symbolic link");

これは *nix に固有のものですが、少なくとも機能します。

于 2012-01-27T22:15:33.830 に答える
1

このような古い投稿に返信して申し訳ありませんが、以前 Windows システムのソリューションを探していましたが、以前の回答のいくつかはうまくいきませんでした。クロス プラットフォームの互換性に関心がなく、Windows のソリューションのみが必要な場合は、次の手法が私の目的に適しています。

File f = new File("whatever file or folder");
if (f instanceof ShellFolder) {
  ShellFolder sf = (ShellFolder)f;
  if (sf.isLink()) {
    // Your code when it's a link
  }
}
于 2011-03-13T17:01:56.163 に答える
-2

この問題に対処することで得た幸運を分かち合いたいと思いました。私は JDK 1.6.0_23 を使用しているため、NIO2 の恩恵を受けることができません。Windows 7 /x64 のみで構築および実行しているため、他の環境では走行距離が異なる場合があります。残念ながら、ここでの他の解決策は、ジャンクションをトラバースしようとしたときに発生する NullPointerExceptions を回避するのにうまくいきませんでした (おそらくジャンクション != symlink .... が原因です)。私は JDK のバージョンに制約されていませんが、もう少しこの問題を扱い続けることにしました。

シンボリック リンクで使用した場合、または「システム ボリューム情報」ディレクトリに遭遇した場合に、NullPointerException を引き起こすこのコードがありました。(traverseItem.f() は java.io.File 型のオブジェクトを返すことに注意してください)

if (traverseItem.f().isDirectory) {
    for (File item : traverseItem.f().listFiles()) {

したがって、おそらくディレクトリですが、その上で listFiles() を呼び出すと NPE が発生します。何をすべきか?list() メソッドを調べて、同じ動作を示すかどうか疑問に思いました。私が発見したのは次のことでした。

空のフォルダーを記述する File で list() を呼び出すと、長さゼロの String[] 配列が返されます。ただし、ジャンクションを記述する File で list() を呼び出すと、それ以外の場合は listFiles() からクラッシュするため、null が返されます。

listFiles() を呼び出す前に次のテストを追加することで、NullPointerExceptions を回避できました。

    String[] contents = traverseItem.f().list();
    if (contents != null) {  //Non-traversible if null, possibly junction or ???

ジャンクション、シンボリック リンク、ハード リンクのすべてのケースを徹底的にテストする必要があります。

于 2011-04-18T10:58:17.177 に答える