Определите, является ли файл соединением (в Windows) или нет?
Я искал, пытаясь найти способ определить, является ли файл соединением или нет, и не нашел удовлетворительных ответов.
Первое, что я пробовал, было:
Files.isSymbolicLink(aPath)
Он обнаруживает только символические ссылки, а не файлы, называемые соединениями в Windows.
Также попробовал предлагаемое здесь решение (используя библиотеку JNA):
qaru.site/info/484453/...
, но он никогда не возвращался ни на один из файлов, которые, как я знаю, являются соединениями.
Единственный способ, с помощью которого я определил, какие файлы являются соединениями, - это следующая команда запуска в командной строке Windows:
DIR /S /A:L
На моем компьютере он возвращает 66 папок, если Files.isSymbolicLink(aPath) вернул только 2.
Поэтому, я полагаю, я мог бы найти способ использовать это, но я не думаю, что это было бы очень эффективно при обходе файла.
Есть ли способ сделать это, используя стандартную java-библиотеку или, альтернативно, JNA?
Ответы
Ответ 1
Если вы можете написать собственный код в JNA, вы можете напрямую вызвать функцию GetFileAttributes()
API Win32 и проверить флаг FILE_ATTRIBUTE_REPARSE_POINT
(соединения реализованы как точки повторной обработки).
Обновление: чтобы различать различные типы точек повторной обработки, необходимо получить ReparseTag
повторной обработки фактической точки повторной обработки. Для точки соединения будет установлено значение IO_REPARSE_TAG_MOUNT_POINT
(0xA0000003).
Есть два способа получить ReparseTag
:
-
Используйте DeviceIoControl()
с управляющим кодом FSCTL_GET_REPARSE_POINT
для получения структуры REPARSE_DATA_BUFFER
, которая является полем ReparseTag
. Вы можете увидеть пример реализации IsDirectoryJunction()
с использованием этого метода в следующей статье:
Жесткие ссылки NTFS, соединения каталогов и ярлыки Windows
-
Используйте 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();