windows 检测符号链接/连接点的跨平台方法?

lyr7nygr  于 2022-12-19  发布在  Windows
关注(0)|答案(4)|浏览(183)

在java中,Unix环境中的符号链接可以通过比较文件的规范路径和绝对路径来检测。然而,这个技巧在windows上不起作用。如果我执行

mkdir c:\foo
mklink /j c:\bar

从命令行,然后在java中执行以下行

File f = new File("C:/bar");
System.out.println(f.getAbsolutePath());
System.out.println(f.getCanonicalPath());

输出为

C:\bar
C:\bar

在Java 7之前的版本中,是否有任何方法可以检测Windows中的连接点?

rqdpfwrv

rqdpfwrv1#

在Java6或更早的版本中似乎没有任何跨平台机制来实现这一点,尽管使用JNA这是一个相当简单的任务

interface Kernel32 extends Library {
  public int GetFileAttributesW(WString fileName);
}

static Kernel32 lib = null;
public static int getWin32FileAttributes(File f) throws IOException { 
  if (lib == null) {
    synchronized (Kernel32.class) {
      lib = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    }
  }
  return lib.GetFileAttributesW(new WString(f.getCanonicalPath()));
}

public static boolean isJunctionOrSymlink(File f) throws IOException {
  if (!f.exists()) { return false; }
  int attributes = getWin32FileAttributes(f);
  if (-1 == attributes) { return false; }
  return ((0x400 & attributes) != 0);
}

编辑:根据getWin32FileAttributes()可能返回错误的评论进行更新

ifmq2ha2

ifmq2ha22#

答案是否定的。连接点和符号链接不是同一类东西。JRE不检查它们,所以你引用的函数不能区分它们。
话虽如此,你可能会完成一些与以下:
如果连接的目录有内容,那么得到它下面某个东西的规范路径名的结果可能是“令人惊讶的”,并揭示了情况,因为它很可能是连接目标下的路径名。当然,只有当连接指向的目录非空时,这才起作用。

jutyujz0

jutyujz03#

有了nio,即使不使用反射或JNA,也可以检测连接/重解析点或符号链接:

public void isReparsePointOrSymlink(Path path) {
    final var attribute = Files.getAttribute(path, "dos:attributes", LinkOption.NOFOLLOW_LINKS);
    if (attribute instanceof Integer value) {
        final boolean isJunctionOrSymlink = (value & 0x400) != 0;
        return isJunctionOrSymlink;
    }
    return Files.isSymbolicLink(path);
}

请注意,Files.isSymbolicLink(path)只为符号链接返回true,而不为重解析点返回true。如果需要区分两者,并且isReparsePointOrSymlink返回true,请同时检查Files.isSymbolicLink

dphi5xsq

dphi5xsq4#

你可以试试这个肮脏的黑客为窗口

if (f.isDirectory() || f.isFile()) {
        System.out.println("File or Directory");
    } else {
        System.out.println("Link");
    }

相关问题