2013-08-14 2 views
7

Vorrei verificare se un file esistente si trova in una directory specifica o in una sottodirectory.Controllare se il file si trova nella (sotto) directory

Ho due oggetti File.

File dir; 
File file; 

Entrambi sono garantiti. Supponiamo

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

voglio questo controllo per tornare vero

Per ora sto facendo il check-in questo modo:

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

Questo sembra funzionare con i miei test limitati, ma io sono sicuro se ciò potrebbe causare problemi su alcuni sistemi operativi. Inoltre non mi piace che getCanonicalPath() possa lanciare una IOException che devo gestire.

C'è un modo migliore? Forse in qualche biblioteca?

Grazie

risposta

-1

Come confrontare i percorsi?

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

o

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

Questo potrebbe essere problematico per i percorsi che contengono cose come "/tmp/something/../dir" che è possibile nella mia applicazione. –

+0

Si può facilmente usare 'child.getAbsolutePath(). StartsWith (parent.getAbsolutePath())' se questo è il caso. – rocketboy

+0

In realtà getAbsolutePath() calcolerà tutti questi token '/../' e restituirà il percorso assoluto assoluto nel file system. –

0

Se si prevede di opere con nomi di file e file di heavly controllare fileutils apache e filenameutils librerie. Sono pieni di utili (e portale se la portabilità è mamdatory) funziona

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

Vorrei creare un piccolo metodo di utilità:

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

Vorrei prima controllare se il file è in realtà un file. E potrebbe non [trovare il genitore] (http://stackoverflow.com/questions/11296949/created-file-has-no-parent). Sembra una buona idea, ma dovrebbe far parte di una soluzione più ampia. –

7

Oltre alla asnwer da Rocketboy, utilizzare getCanonicalPath() instad di getAbsolutePath() così \dir\dir2\..\file viene convertito in \dir\file:

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

o

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

Non dimenticare di prendere qualsiasi Exception con try {...} catch {...}.

NOTA: è possibile utilizzare FileSystem.getSeparator() anziché File.separator. Il modo "corretto" per farlo sarà quello di ottenere il getCanonicalPath() della directory che si desidera controllare come String, quindi controllare se termina con uno File.separator e se non lo è, aggiungere File.separator alla fine di quello String, per evitare doppie barre.In questo modo salti i comportamenti dispari futuri se Java decide di restituire le directory con una barra alla fine o se la tua stringa di directory proviene da qualcos'altro oltre allo Java.io.File.

NOTA2: Grazie a @david per indicare il problema File.separator.

+0

Che dire di '/ a' e'/ab/test.txt'? – david

+0

@david Restituirà esattamente lo stesso. Se chiedi barrature invece di barre rovesciate, non conosco il comportamento, ma il mio consiglio è di usare OS nativo. Java ha una funzione per restituire il separatore di directory nativa del sistema operativo, ma non lo ricordo in questo momento. –

+0

Il mio punto non riguardava affatto la direzione dei tagli; Stavo dando un contro esempio che si tradurrà in una risposta errata utilizzando la strategia nella tua risposta. – david

4

Questo metodo sembra piuttosto solido:

/** 
* 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

E 'simile alla soluzione da dacwe ma non fa uso di ricorsione (anche se questo non dovrebbe fare una grande differenza in questo caso) .

Problemi correlati