Java 1.6 - определение символических ссылок
В классе DirectoryWalker я хочу узнать, действительно ли экземпляр File является символической ссылкой на каталог (при условии, что ходок работает в системах UNIX). Учитывая, что я уже знаю, что экземпляр является каталогом, может ли быть следующим условием для определения символической ссылки?
File file;
// ...
if (file.getAbsolutePath().equals(file.getCanonicalPath())) {
// real directory ---> do normal stuff
}
else {
// possible symbolic link ---> do link stuff
}
Ответы
Ответ 1
Техника, используемая в Apache Commons, использует канонический путь к родительскому каталогу, а не к самому файлу. Я не думаю, что вы можете гарантировать, что несоответствие связано с символической ссылкой, но это хороший признак того, что файл нуждается в специальном лечении.
Это код Apache (при условии их лицензия), модифицированный для компактности.
public static boolean isSymlink(File file) throws IOException {
if (file == null)
throw new NullPointerException("File must not be null");
File canon;
if (file.getParent() == null) {
canon = file;
} else {
File canonDir = file.getParentFile().getCanonicalFile();
canon = new File(canonDir, file.getName());
}
return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
}
Ответ 2
Java 1.6 не обеспечивает такой низкий уровень доступа к файловой системе. Похоже, NIO 2, который должен быть включен в Java 1.7, будет поддерживать символические ссылки. Доступен проект нового API. Символические ссылки упоминаются там, создание и после их возможно. Я не совсем уверен, что какой метод следует использовать, чтобы выяснить, является ли файл символической ссылкой. Там список рассылки для обсуждения NIO 2 - может быть, они будут знать.
Ответ 3
Также следите за тем, чтобы file.isFile()
и file.isDirectory()
возвращали результаты на основе разрешенного файла и поэтому возвращали false
, когда file
ссылается на символическую ссылку, где цель не существует.
(Я знаю, что это не самый полезный ответ сам по себе, но он несколько раз опрокинул меня, поэтому я подумал, что должен поделиться)
Ответ 4
Похоже, getCanonicalPath()
может делать другие вещи, которые могут отличить его от абсолютного пути.
Этот метод сначала преобразует этот путь в абсолютную форму, если это необходимо, как если бы он вызывал метод getAbsolutePath(), а затем сопоставлял его с его уникальной формой зависящим от системы образом. Обычно это связано с удалением избыточных имен, таких как ".". и ".." из имени пути, разрешения символических ссылок (на платформах UNIX) и преобразования букв дисков в стандартный пример (на платформах Microsoft Windows).
Но это может сработать для подавляющего большинства ваших случаев использования; ваш пробег может меняться.
Ответ 5
Если вы уже кодируете что-то специально для * nix, тогда вы можете сделать команду оболочки из Java следующим образом:
Process p = Runtime.getRuntime().exec(new String[]{"test", "-h", yourFileName});
p.waitFor();
if (p.exitValue() == 0)
System.out.println("This file is a symbolic link");
else
System.out.println("This file is not a symbolic link");
Это очень специфично для * nix, но, по крайней мере, работает.
Ответ 6
Извините, что ответил на такое старое сообщение, но некоторое время назад искал решение для систем Windows, и некоторые из предыдущих ответов не сработали для меня. Если вам не нужна совместимость с кросс-платформой и требуется только решение для Windows, следующий метод работал хорошо для моих целей.
File f = new File("whatever file or folder");
if (f instanceof ShellFolder) {
ShellFolder sf = (ShellFolder)f;
if (sf.isLink()) {
// Your code when it a link
}
}
Ответ 7
Я думал, что поделился бы некоторой удачей, с которой я столкнулся с этой проблемой. Я использую JDK 1.6.0_23, поэтому я не могу воспользоваться NIO2. Я только создаю и запускаю Windows 7/x64, поэтому пробег может отличаться в других средах. К сожалению, другие решения здесь не сработали для меня, избегая NullPointerExceptions, возникающих при попытке пересечения перехода (возможно, потому что соединение!= Символическая связь....). Хотя я не ограничена версией JDK, я решил немного продолжить эту проблему.
У меня был этот код, который вызвал бы исключение NullPointerException, если он используется в символической ссылке или когда вы сталкиваетесь с каталогом "Сведения о системном томе". (Обратите внимание: traverseItem.f() возвращает объект типа java.io.File)
if (traverseItem.f().isDirectory) {
for (File item : traverseItem.f().listFiles()) {
Итак, это, предположительно, каталог, но вызов listFiles() на нем вызывает NPE. Что делать? Я попробовал метод list() и задался вопросом, будет ли он демонстрировать такое же поведение. Я обнаружил следующее:
Вызывающий список() в файле, описывающем пустую папку, возвращает массив String [] с нулевой длиной. Однако вызов списка() в файле, описывающем соединение, которое в противном случае вышло бы из списка listFiles(), возвращает null
Мне удалось избежать NullPointerExceptions, добавив следующий тест перед вызовом listFiles()
String[] contents = traverseItem.f().list();
if (contents != null) { //Non-traversible if null, possibly junction or ???
Остается исчерпывающим образом проверить все случаи соединения, символическую ссылку, жесткую ссылку и осмелюсь упомянуть ее, ярлык, но это может помочь некоторым.