Java 1.6 - определить символические ссылки - PullRequest
41 голосов
/ 02 мая 2009

В классе DirectoryWalker я хочу выяснить, является ли экземпляр File на самом деле символической ссылкой на каталог (при условии, что обходчик работает в системах UNIX). Учитывая, что я уже знаю, что экземпляр является каталогом, будет ли следующее условие надежным для определения символической ссылки?

File file;
// ...      
if (file.getAbsolutePath().equals(file.getCanonicalPath())) {
    // real directory ---> do normal stuff      
}
else {
    // possible symbolic link ---> do link stuff
}

Ответы [ 7 ]

45 голосов
/ 02 мая 2009

Техника, используемая в 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());
}
13 голосов
/ 02 мая 2009

Java 1.6 не обеспечивает такой низкоуровневый доступ к файловой системе. Похоже, что NIO 2 , который должен быть включен в Java 1.7, будет иметь поддержку символических ссылок. Доступен черновой вариант нового API . Здесь упоминаются символические ссылки , , возможно создание и , следующие . Я не совсем уверен, какой метод следует использовать, чтобы узнать, является ли файл символической ссылкой. список рассылки для обсуждения NIO 2 - возможно, они узнают.

11 голосов
/ 11 октября 2011

Кроме того, обратите внимание на то, что file.isFile() и file.isDirectory() оба возвращают результаты на основе разрешенного файла, и поэтому оба возвращают false, когда file ссылается на символическую ссылку, где цель не существует.

(я знаю, что это не очень полезный ответ сам по себе, но он пару раз сбил меня с толку, поэтому я подумал, что должен поделиться)

5 голосов
/ 02 мая 2009

Похоже, getCanonicalPath() может делать другие вещи, которые могут отличать его от абсолютного пути.

Этот метод сначала преобразовывает это имя пути в абсолютную форму, если это необходимо, как если бы он вызывал метод getAbsolutePath (), а затем отображал его уникальную форму системно-зависимым способом. Обычно это включает в себя удаление избыточных имен, таких как "." и ".." из имени пути, разрешая символические ссылки (на платформах UNIX) и преобразовывая буквы дисков в стандартный регистр (на платформах Microsoft Windows).

Но это может работать для подавляющего большинства ваших вариантов использования; Ваш пробег может варьироваться.

3 голосов
/ 28 января 2012

Если вы уже пишете что-то специально для * 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, но, по крайней мере, работает.

1 голос
/ 13 марта 2011

Извините, что отвечаю на такой старый пост, но некоторое время назад я искал решение для систем 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's a link
  }
}
0 голосов
/ 18 апреля 2011

Я думал, что поделюсь своим счастьем в решении этой проблемы. Я использую JDK 1.6.0_23 и поэтому не могу извлечь выгоду из NIO2. Я строю и работаю только на Windows 7 / x64, поэтому пробег может отличаться в других средах. К сожалению, другие решения здесь не помогли мне избежать исключений NullPointerException, возникающих при попытке пройти через соединение (вероятно, из-за соединения! = Символическая ссылка ....). Хотя я не ограничен версией JDK, я решил немного подождать с этой проблемой.

У меня был этот код, который вызывал бы исключение NullPointerException, если бы он использовался для символической ссылки или при обращении к каталогу «System Volume Information» (Обратите внимание, traverseItem.f () возвращает объект типа java.io.File)

if (traverseItem.f().isDirectory) {
    for (File item : traverseItem.f().listFiles()) {

Итак, это предположительно каталог, но вызов listFiles () для него вызывает NPE. Что делать? Я заметил метод list () и подумал, будет ли он демонстрировать такое же поведение. Я обнаружил следующее:

Вызов list () для файла, описывающего пустую папку, возвращает массив String [] нулевой длины. Однако вызов list () для файла, описывающего соединение, которое в противном случае вылетало бы из listFiles (), возвращает null

Мне удалось избежать исключений NullPointerException, добавив следующий тест перед вызовом listFiles ()

    String[] contents = traverseItem.f().list();
    if (contents != null) {  //Non-traversible if null, possibly junction or ???

Остается провести исчерпывающую проверку всех случаев перехода, символической ссылки, жесткой ссылки и, смею упомянуть, ярлыка, но это может помочь некоторым.

...