Подтвердить что ты не робот

Определите, является ли файл соединением (в Windows) или нет?

Я искал, пытаясь найти способ определить, является ли файл соединением или нет, и не нашел удовлетворительных ответов.

Первое, что я пробовал, было:

Files.isSymbolicLink(aPath)

Он обнаруживает только символические ссылки, а не файлы, называемые соединениями в Windows.

Также попробовал предлагаемое здесь решение (используя библиотеку JNA): qaru.site/info/484453/... , но он никогда не возвращался ни на один из файлов, которые, как я знаю, являются соединениями.

Единственный способ, с помощью которого я определил, какие файлы являются соединениями, - это следующая команда запуска в командной строке Windows:

DIR /S /A:L

На моем компьютере он возвращает 66 папок, если Files.isSymbolicLink(aPath) вернул только 2. Поэтому, я полагаю, я мог бы найти способ использовать это, но я не думаю, что это было бы очень эффективно при обходе файла.

Есть ли способ сделать это, используя стандартную java-библиотеку или, альтернативно, JNA?

4b9b3361

Ответ 1

Если вы можете написать собственный код в JNA, вы можете напрямую вызвать функцию GetFileAttributes() API Win32 и проверить флаг 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.

Ответ 2

Может быть способ сделать это без JNA, если у вас есть правильная java, например, Oracle jdk 8. Это изворотливое, оно может перестать работать, но....

Вы можете получить интерфейс 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)

Если его нет, но это точка повторной обработки, то это соединение.

Ответ 3

С 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;
}

Ответ 4

В то время как в Windows атрибуты соединения имеют isSymbolicLink() == false, они имеют isOther() == true. Таким образом, вы можете сделать что-то вроде:

boolean isWindows = System.getProperty("os.name").toLowerCase().contains("windows")
BasicFileAttributes attrs = Files.readAttributes(aPath, BasicFileAttributes.class);
boolean isJunction = isWindows && attrs.isDirectory() && attrs.isOther();