You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java 17检测两个Path是否为同一硬链接文件?

验证两个Path是否指向同一硬链接(Java 17)

跨平台通用方案:Files.isSameFile()

Java标准库的Files.isSameFile()方法可直接判断两个Path是否指向磁盘上的同一文件实体(包括硬链接),会自动适配不同操作系统的底层逻辑:

import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;

public class HardLinkValidator {
    public static boolean areSameHardLink(Path path1, Path path2) {
        try {
            // 题目已说明共享同一FileStore,可省略此判断
            if (!Files.getFileStore(path1).equals(Files.getFileStore(path2))) {
                return false;
            }
            return Files.isSameFile(path1, path2);
        } catch (IOException e) {
            // 处理文件不存在、权限不足等异常
            return false;
        }
    }
}

注意:若任一文件不存在,该方法会抛出IOException,需做好异常捕获。


Unix类系统(Linux/macOS等)进阶验证

Unix系统中,同一硬链接的文件拥有相同的inode编号,可通过获取unix:ino属性判断:

public static boolean areSameHardLinkUnix(Path path1, Path path2) throws IOException {
    if (!Files.getFileStore(path1).equals(Files.getFileStore(path2))) {
        return false;
    }
    // 获取inode编号
    long inode1 = (long) Files.getAttribute(path1, "unix:ino");
    long inode2 = (long) Files.getAttribute(path2, "unix:ino");
    return inode1 == inode2;
}

若要判断文件是否存在其他硬链接,可获取硬链接计数属性unix:nlink:

long linkCount = (long) Files.getAttribute(path, "unix:nlink");
if (linkCount > 1) {
    // 文件存在其他硬链接
}

Windows/NTFS系统专项方案

方案1:调用fsutil命令解析输出

执行系统命令fsutil hardlink list <file-path>获取所有硬链接路径,再验证目标路径是否在列表中:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.nio.file.Path;

public class WindowsHardLinkUtils {
    public static List<String> getHardLinkList(Path path) throws Exception {
        List<String> links = new ArrayList<>();
        Process process = new ProcessBuilder("fsutil", "hardlink", "list", path.toString()).start();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                links.add(line.trim());
            }
        }
        process.waitFor();
        return links;
    }

    public static boolean areSameHardLinkWindows(Path path1, Path path2) throws Exception {
        return getHardLinkList(path1).contains(path2.toString());
    }
}

方案2:JNA调用Windows原生API

通过JNA调用GetFileInformationByHandle获取文件的唯一标识(卷序列号+文件索引),同一硬链接的标识完全一致:

  1. 引入JNA依赖(以Maven为例):
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.13.0</version>
</dependency>
  1. 编写验证代码:
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinBase;
import java.nio.file.Path;
import java.io.IOException;

public class JNAHardLinkValidator {
    public static boolean areSameHardLink(Path path1, Path path2) throws IOException {
        // 打开文件句柄
        WinNT.HANDLE handle1 = Kernel32.INSTANCE.CreateFile(
                path1.toString(),
                WinNT.GENERIC_READ,
                WinNT.FILE_SHARE_READ | WinNT.FILE_SHARE_WRITE | WinNT.FILE_SHARE_DELETE,
                null,
                WinNT.OPEN_EXISTING,
                WinBase.FILE_ATTRIBUTE_NORMAL,
                null
        );
        WinNT.HANDLE handle2 = Kernel32.INSTANCE.CreateFile(
                path2.toString(),
                WinNT.GENERIC_READ,
                WinNT.FILE_SHARE_READ | WinNT.FILE_SHARE_WRITE | WinNT.FILE_SHARE_DELETE,
                null,
                WinNT.OPEN_EXISTING,
                WinBase.FILE_ATTRIBUTE_NORMAL,
                null
        );

        try {
            if (WinNT.INVALID_HANDLE_VALUE.equals(handle1) || WinNT.INVALID_HANDLE_VALUE.equals(handle2)) {
                throw new IOException("无法打开文件句柄");
            }

            WinBase.BY_HANDLE_FILE_INFORMATION info1 = new WinBase.BY_HANDLE_FILE_INFORMATION();
            WinBase.BY_HANDLE_FILE_INFORMATION info2 = new WinBase.BY_HANDLE_FILE_INFORMATION();

            if (!Kernel32.INSTANCE.GetFileInformationByHandle(handle1, info1) ||
                !Kernel32.INSTANCE.GetFileInformationByHandle(handle2, info2)) {
                throw new IOException("无法获取文件信息");
            }

            // 比较卷序列号和文件索引(高低位)
            return info1.dwVolumeSerialNumber.equals(info2.dwVolumeSerialNumber) &&
                   info1.nFileIndexHigh.equals(info2.nFileIndexHigh) &&
                   info1.nFileIndexLow.equals(info2.nFileIndexLow);
        } finally {
            // 关闭句柄
            Kernel32.INSTANCE.CloseHandle(handle1);
            Kernel32.INSTANCE.CloseHandle(handle2);
        }
    }
}

内容的提问来源于stack exchange,提问作者Thomas S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:55:25