Java 1.6 - 确定符号链接

时间:2009-05-01 23:31:37

标签: java java-6

在DirectoryWalker类中,我想知道File实例是否实际上是指向目录的符号链接(假设,walker在UNIX系统上行走)。鉴于,我已经知道实例是一个目录,以下是确定符号链接的可靠条件吗?

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

7 个答案:

答案 0 :(得分:45)

Apache Commons中使用的技术使用父目录的规范路径,而不是文件本身。我不认为您可以保证不匹配是由于符号链接,但它是一个很好的迹象表明该文件需要特殊处理。

这是Apache code(受their license约束),已针对紧凑性进行了修改。

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());
}

答案 1 :(得分:13)

Java 1.6不提供对文件系统的低级访问。看起来应该包含在Java 1.7中的NIO 2将支持符号链接。 A draft of the new API可用。符号链接are mentioned therecreatingfollowing是可能的。我不确定应该使用哪种方法来确定文件是否是符号链接。讨论NIO 2有a mailing list - 也许他们会知道。

答案 2 :(得分:11)

另外,请注意file.isFile()file.isDirectory()两者都根据已解析的文件返回结果,因此当false引用目标不存在的符号链接时返回file不存在。

(我知道这本身并不是一个有用的答案,但它让我吵了几次,以为我应该分享一下)

答案 3 :(得分:5)

看起来getCanonicalPath()可以做其他可能与绝对路径不同的事情。

  

此方法首先在必要时将此路径名转换为绝对形式,就像调用getAbsolutePath()方法一样,然后以系统相关的方式将其映射到其唯一形式。这通常涉及删除冗余名称,例如“。”和路径名中的“..”,解析符号链接(在UNIX平台上),并将驱动器号转换为标准情况(在Microsoft Windows平台上)。

但它可能适用于绝大多数用例;你的里程可能会有所不同。

答案 4 :(得分:3)

如果您已经专门为* nix编写了一些代码,那么您可以像这样从Java执行shell命令:

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非常具体,但至少可以起作用。

答案 5 :(得分: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
  }
}

答案 6 :(得分:-2)

我以为我会在处理这个问题时分享一些好运。我正在使用JDK 1.6.0_23,所以我无法从NIO2中受益。我只在Windows 7 / x64上构建和运行,因此在其他环境中里程可能会有所不同。不幸的是,这里的其他解决方案对我来说并不适用于避免在尝试遍历联结时导致的NullPointerExceptions(可能是因为联结!=符号链接....)。虽然我不受JDK版本的限制,但我决定将问题延长一段时间。

我有这个代码,如果在符号链接上使用或遇到'System Volume Information'目录时会导致NullPointerException。 (注意,traverseItem.f()返回java.io.File类型的对象)

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

因此,它应该是一个目录,但在其上调用listFiles()会导致NPE。该怎么办?我发现了list()方法,并想知道它是否会表现出相同的行为。我发现的是以下内容:

在描述空文件夹的文件上调用list()会返回长度为零的String []数组。但是,在描述结点的文件上调用list(),否则会从listFiles()崩溃,返回null

通过在调用listFiles()

之前添加以下测试,我能够避免NullPointerExceptions
    String[] contents = traverseItem.f().list();
    if (contents != null) {  //Non-traversible if null, possibly junction or ???

仍然要详尽地测试所有结点,符号链接,硬链接的情况,并且我敢提及它,快捷方式,但这可能有所帮助。