确定文件是否是连接(在Windows中)?

我一直在四处搜寻,试图find一种方法来确定一个文件是否是一个交叉点,并没有find任何满意的答案。

我尝试的第一件事是:

Files.isSymbolicLink(aPath) 

它只检测符号链接,而不是在Windows中被称为连接点的文件。

也尝试了这里提出的解决scheme(使用JNA库): Stackoverflow的问题(3249117) ,但它从来没有返回真正的任何文件,我知道是路口。

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

 DIR /S /A:L 

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

有没有办法做到这一点使用标准的Java库,或者替代JNA?

如果您可以在JNA中编写本机代码,则可以直接调用Win32 API的GetFileAttributes()函数并检查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

如果你有正确的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)

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

使用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; }