44

在 DirectoryWalker 类中,我想知道 File 实例是否实际上是指向目录的符号链接(假设 walker 在 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 执行一个 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 特有的,但它至少可以工作。

于 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 对我不起作用(可能是因为 junction != symlink ....)。虽然我不受 JDK 版本的限制,但我决定在这个问题上再坚持一段时间。

我有这段代码,如果在符号链接上使用或遇到“系统卷信息”目录时会导致 NullPointerException。(注意,traverseItem.f() 返回一个 java.io.File 类型的对象)

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

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

对描述空文件夹的 File 调用 list() 会返回一个长度为零的 String[] 数组。但是,在描述一个结点的文件上调用 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 回答