2013-08-14 4 views
7

Я хотел бы проверить, находится ли существующий файл в определенном каталоге или в его подкаталоге.Проверьте, находится ли файл в (под) каталоге

У меня есть два объекта File.

File dir; 
File file; 

Оба гарантированно будут существовать. Давайте предположим, что

dir = /tmp/dir 
file = /tmp/dir/subdir1/subdir2/file.txt 

Я хочу, чтобы эта проверка, чтобы вернуть истинный

На данный момент я делаю чек так:

String canonicalDir = dir.getCanonicalPath() + File.separator; 
boolean subdir = file.getCanonicalPath().startsWith(canonicalDir); 

Это похоже на работу с моими ограниченными тестов, но я не уверен, может ли это возникнуть в некоторых операционных системах. Мне также не нравится, что getCanonicalPath() может вызывать исключение IOException, с которым я должен обращаться.

Есть ли лучший способ? Возможно, в какой-то библиотеке?

Thanks

ответ

-1

Как насчет сравнения путей?

boolean areRelated = file.getAbsolutePath().contains(dir.getAbsolutePath()); 
    System.out.println(areRelated); 

или

boolean areRelated = child.getAbsolutePath().startsWith(parent.getAbsolutePath()) 
+2

Это может быть проблематично для путей, которые содержат такие вещи, как «/tmp/something/../dir», что возможно в моем приложении. –

+0

Вы можете легко использовать 'child.getAbsolutePath(). StartsWith (parent.getAbsolutePath()), если это так. – rocketboy

+0

Фактически getAbsolutePath() будет вычислять все такие маркеры «/../» и возвращать реальный абсолютный путь в файловой системе. –

0

Если вы планируете работу с файлами и именами файлами heavly проверить Apache FileUtils и filenameutils библиотеки. Полны полезно (и Portale если портативность mamdatory) функции

0
public class Test { 
public static void main(String[] args) { 
    File root = new File("c:\\test"); 
    String fileName = "a.txt"; 
    try { 
     boolean recursive = true; 

     Collection files = FileUtils.listFiles(root, null, recursive); 

     for (Iterator iterator = files.iterator(); iterator.hasNext();) { 
      File file = (File) iterator.next(); 
      if (file.getName().equals(fileName)) 
       System.out.println(file.getAbsolutePath()); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

}

10

Я хотел бы создать небольшой служебный метод:

public static boolean isInSubDirectory(File dir, File file) { 

    if (file == null) 
     return false; 

    if (file.equals(dir)) 
     return true; 

    return isInSubDirectory(dir, file.getParentFile()); 
} 
+2

Я бы сначала проверил, действительно ли файл на самом деле является файлом. И это может не [найти родителя] (http://stackoverflow.com/questions/11296949/created-file-has-no-parent). Это звучит неплохо, но это должно быть частью большего решения. –

0

Вы можете траверс дерево файлов, начиная с вашего конкретного DIR , На Java 7 существует метод Files.walkFileTree. Вам нужно написать свой собственный посетитель , чтобы проверить, найден ли текущий файл поиска. Больше документ: http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java.util.Set,%20int,%20java.nio.file.FileVisitor%29

7

В дополнение к asnwer из Rocketboy, используйте getCanonicalPath() вместо внесения getAbsolutePath() так \dir\dir2\..\file превращается в \dir\file:

boolean areRelated = file.getCanonicalPath().contains(dir.getCanonicalPath() + File.separator); 
    System.out.println(areRelated); 

или

boolean areRelated = child.getCanonicalPath().startsWith(parent.getCanonicalPath() + File.separator); 

Не забудьте поймать любой Exception с try {...} catch {...}.

ПРИМЕЧАНИЕ. Вы можете использовать FileSystem.getSeparator() вместо File.separator. «Правильный» способ сделать это - получить getCanonicalPath() каталога, который вы собираетесь проверить, как String, а затем проверить, заканчивается ли оно File.separator, а если нет, то добавьте File.separator в конец этого String, чтобы избежать двойные косые черты.Таким образом, вы пропускаете будущее нечетное поведение, если Java решает вернуть каталоги с косой чертой в конце или если ваша строка каталога приходит откуда-то еще, чем Java.io.File.

NOTE2: Thanx to @david для указания проблемы File.separator.

+0

Как насчет '/ a' и'/ab/test.txt'? – david

+0

@david Вернет точно то же самое. Если вы попросите косые черты вместо обратных косых черт, я не знаю этого поведения, но моя рекомендация - использовать ОС. У Java есть функция, чтобы вернуть собственный разделитель каталогов ОС, но я не помню его прямо сейчас. –

+0

Моя мысль была не о направлении косых черт; Я приводил встречный пример, который приведет к неправильному ответу, используя стратегию в вашем ответе. – david

4

Этот метод выглядит довольно твердый:

/** 
* Checks, whether the child directory is a subdirectory of the base 
* directory. 
* 
* @param base the base directory. 
* @param child the suspected child directory. 
* @return true, if the child is a subdirectory of the base directory. 
* @throws IOException if an IOError occured during the test. 
*/ 
public boolean isSubDirectory(File base, File child) 
    throws IOException { 
    base = base.getCanonicalFile(); 
    child = child.getCanonicalFile(); 

    File parentFile = child; 
    while (parentFile != null) { 
     if (base.equals(parentFile)) { 
      return true; 
     } 
     parentFile = parentFile.getParentFile(); 
    } 
    return false; 
} 

Source

Это аналогично решению по dacwe, но не использует рекурсию (хотя это не должно иметь большое значение в данном случае) ,

Смежные вопросы