15

我一直在寻找一种方法来确定文件是否为连接,但没有找到任何令人满意的答案。

我尝试的第一件事是:

Files.isSymbolicLink(aPath)

它只检测符号链接而不是 Windows 中称为联结的文件。

还尝试了此处提出的解决方案(使用 JNA 库): Stackoverflow question (3249117) ,但它从未在我知道是联结的任何文件上返回 true。

我发现确定哪些文件是联结的唯一方法是在 Windows 命令提示符下运行以下命令:

DIR /S /A:L

在我的计算机上,它返回 66 个文件夹,而 Files.isSymbolicLink(aPath) 只返回 2 个。所以我想我可以找到一种方法来利用它,但我认为在遍历文件树时它不会非常有效。

有没有办法使用标准的java库或alternativly JNA来做到这一点?

4

5 回答 5

9

如果您有正确的 java,例如 Oracle jdk 8,则可以在没有 JNA 的情况下做到这一点。它很狡猾,它可能会停止工作,但是....

可以获取链接相关的BasicFileAttributes接口:

BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);

这个接口实现可能是一个类 sun.nio.fs.WindowsFileAttributes。并且这个类有一个方法isReparsePoint,它对连接点和符号链接都返回 true。所以你可以尝试使用反射并调用方法:

    boolean isReparsePoint = false;
    if (DosFileAttributes.class.isInstance(attr))
        try {
            Method m = attr.getClass().getDeclaredMethod("isReparsePoint");
            m.setAccessible(true);
            isReparsePoint = (boolean) m.invoke(attr);
        } catch (Exception e) {
            // just gave it a try
        }

现在你只能发现它是否真的是符号链接:Files.isSymbolicLink(path)

如果不是,但它是重解析点,那么这就是交界处。

于 2015-04-15T10:30:14.353 回答
7

如果您可以在 JNA 中编写本机代码,则可以直接调用 Win32 APIGetFileAttributes()函数并检查FILE_ATTRIBUTE_REPARSE_POINT标志(连接被实现为重解析点)。

更新:要区分不同类型的重解析点,您必须检索ReparseTag实际重解析点的。对于连接点,它将被设置为IO_REPARSE_TAG_MOUNT_POINT(0xA0000003)。

有两种方法可以获取ReparseTag

  1. DeviceIoControl()与控制代码一起使用FSCTL_GET_REPARSE_POINT来获得一个REPARSE_DATA_BUFFER结构,它作为一个ReparseTag字段。IsDirectoryJunction()您可以在以下文章中看到使用此技术的实现示例:

    NTFS 硬链接、目录连接和 Windows 快捷方式

  2. 用于FindFirstFile()获取WIN32_FIND_DATA结构。如果路径具有FILE_ATTRIBUTE_REPARSE_POINT属性,则该dwReserved0字段将包含ReparseTag.

于 2012-12-05T22:19:33.743 回答
7

在 J2SE 1.7 中使用 Java NIO

/**
* returns true if the Path is a Windows Junction
*/
private static boolean isJunction(Path p) {
    boolean isJunction = false;
    try {
        isJunction = (p.compareTo(p.toRealPath()) != 0);
    } catch (IOException e) {
        e.printStackTrace(); // TODO: handleMeProperly
    }
    return isJunction;
}
于 2015-04-17T12:38:59.380 回答
5

虽然在 Windows 上,联结的属性具有isSymbolicLink()== false,但它们具有isOther()== true。因此,您可以执行以下操作:

boolean isWindows = System.getProperty("os.name").toLowerCase().contains("windows")
BasicFileAttributes attrs = Files.readAttributes(aPath, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
boolean isJunction = isWindows && attrs.isDirectory() && attrs.isOther();
于 2018-01-16T23:30:28.797 回答
0

黑盒解决方案:

aPath.toRealPath()解析交汇点和符号链接,因此结果将偏离aPath.

此外,出于未记录的原因为路口BasicFileAttributes.isSymbolicLink()交付:false

例如Path.toRealPath(LinkOption.NOFOLLOW_LINKS),将连接视为链接并不能解决它!

因此,通过非同一性,toRealPath()BasicFileAttributes.isSymbolicLink()可以识别一个连接点。

于 2021-09-04T16:20:46.850 回答