2016-01-05 18 views
13

Uso questa funzione per rilevare se il mio file esiste o meno. Mentre ho alcune immagini memorizzate come .jpg, .JPG, .png e .PNG. Ma restituisce sempre .jpg o .png come vero anche se il file reale ha estensione .JPG o .PNG.Il file Java esiste Case sensitive .jpg e .JPG

Dopo il rendering sulla mia pagina Web genera un errore "Impossibile caricare la risorsa: il server ha risposto con uno stato di 404 (non trovato)".

public static String getPhotoFileExtension(int empKey){ 
    try{ 
     String[] types = {".jpg",".JPG",".png", ".PNG"}; 
     for(String t : types) 
     { 
      String path = "/"+Common.PHOTO_PATH + empKey + t; 
      File f = new File(Sessions.getCurrent().getWebApp() 
        .getRealPath(path)); 
      if(f.isFile()) 
       return t; 
     } 
    }catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return ""; 
} 
+1

No, quella domanda chiede come caricare Abc.txt da abc.txt. Chiedo come rilevare se esiste abc.txt o abc.TXT. –

+0

Ogni dipendente ha un'immagine, ma memorizza in diverse estensioni jpg JPG png o PNG. ma la mia funzione restituisce sempre jpg o png mentre l'estensione esistente è JPG o PNG –

+0

@John Hascal restituisce sempre l'estensione minuscola –

risposta

16

Così si desidera ottenere i nomi sensibili casi reali di file memorizzati nel file system. Consente di imaging abbiamo i seguenti percorsi:

  • su Linux: utilizzando ext4 (che è case sensitive) /testFolder/test.PnG
  • su di Windows utilizzando NTFS (che non è caso sensibile) c:\testFolder\test.PnG

No w consente di creare alcuni oggetti Java File in ciascun file immagine.

// on Linux 
File f1 = new File("/testFolder/test.png"); 
File f2 = new File("/testFolder/test.PNG"); 
File f3 = new File("/testFolder/test.PnG"); 
f1.exists(); // false 
f2.exists(); // false 
f3.exists(); // true 

// on Windows 
File f1 = new File("c:\\testFolder\\test.png"); 
File f2 = new File("c:\\testFolder\\test.PNG"); 
File f3 = new File("c:\\testFolder\\test.PnG"); 
f1.exists(); // true 
f2.exists(); // true 
f3.exists(); // true 

Il tuo problema è che tutte le chiamate di File come File.exists vengono reindirizzati alla classe java.io.FileSystem che rappresenta le chiamate vero sistema operativo del vostro file system da parte del JVM. Quindi non è possibile distinguere su macchine Windows tra test.PNG e test.png. Neanche Windows stesso.
Ma anche su Windows ogni File ha un nome definito nel File System che potrebbe essere ad esempio: test.PnG. Lo vedrai nel tuo Windows Explorer o nella riga di comando se scrivi dir c:\testFolder.

Quindi, ciò che è possibile fare in Java è utilizzare il metodo File.list su parent directory che risulta nella chiamata dell'elenco Sistema operativo per tutti i file in questa directory con i loro nomi reali.

File dir = new File("c://testFolder//"); 
for(String fileName : dir.list()) 
    System.out.println(fileName); 
// OUTPUT: test.PnG 

o se si preferisce File oggetti

File dir = new File("c://testFolder//"); 
for(File file : dir.listFiles()) 
    System.out.println(file.getName()); 
// OUTPUT: test.PnG 

È possibile utilizzare questo per scrivere il proprio exists metodo che è case sensitive su tutti i sistemi operativi

public boolean exists(File dir, String filename){ 
    String[] files = dir.list(); 
    for(String file : files) 
     if(file.equals(filename)) 
      return true; 
    return false; 
} 

usare in questo modo:

File dir = new File("c:\\testFolder\\"); 
exists(dir, "test.png"); // false 
exists(dir, "test.PNG"); // false 
exists(dir, "test.PnG"); // true 



EDIT: Devo ammettere che ho sbagliato. C'è un modo per ottenere il vero nome di un file. Ho sempre trascurato il metodo File.getCanonicalPath.
Ancora il nostro esempio: abbiamo quel file c:\testFolder\test.PnG.

File f = new File("c://testFolder//test.png"); 
System.out.println(f.getCanonicalPath()); 
// OUTPUT: C:\testFolder\test.PnG 

Con questa conoscenza è possibile scrivere un metodo di prova semplice per l'estensione sensibili caso senza l'iterazione di tutti i file.

public boolean checkExtensionCaseSensitive(File _file, String _extension) throws IOException{ 
    String canonicalPath = _file.getCanonicalPath(); 
    String extension = ""; 
    int i = canonicalPath.lastIndexOf('.'); 
    if (i > 0) { 
     extension = canonicalPath.substring(i+1); 
     if(extension.equals(_extension)) 
      return true; 
    } 
    return false; 
} 

Utilizzare in questo modo:

File f = new File("c://testFolder//test.png");  
checkExtensionCaseSensitive(f, "png"); // false 
checkExtensionCaseSensitive(f, "PNG"); // false 
checkExtensionCaseSensitive(f, "PnG"); // true 
+0

'File.getCanonicalPath()' è, almeno con il mio setup, non un modo affidabile per ottenere il vero nome del file. Ho scritto una piccola classe che stampa ripetutamente il risultato di 'File.getCanonicalPath()' nella console di Eclipse. Mentre il programma è in esecuzione, rinominando il file "abc.txt" in "Abc.txt" risulta in 'getCanonicalPath()' sta ancora restituendo "abc.txt ", fino a quando non riavvio il programma/JVM. Il mio setup è JDK 6u45 e Windows 10. Ho dovuto usare una soluzione basata sull'espressione' ArrayUtils.contains (parentFile.list(), realFileName) '. –

3

Se siete alla ricerca di una funzione che in qualsiasi piattaforma in grado di determinare l'esistenza di un file ed è case-sensitive; questo dovrebbe farlo:

public static boolean fileExistsCaseSensitive(String path) { 
    try { 
     File file = new File(path); 
     return file.exists() && file.getCanonicalFile().getName().equals(file.getName()); 
    } catch (IOException e) { 
     return false; 
    } 
} 
2

ho iniziato fare in giro un po 'con questo perché non ho usato IOFileFilter di Apache prima e ho pensato che vorrei aggiungere questa soluzione come la possibilità di giocare con un po'.

Ecco il codice:

import java.io.File; 
import java.util.Collection; 
import java.util.Optional; 

import org.apache.commons.io.FileUtils; 
import org.apache.commons.io.filefilter.IOFileFilter; 

public class CaseInsensitiveFileFinder { 

    /** 
    * Attempts to find a file with the given <code>fileName</code> (irrespective of case) in the given 
    * <code>absoluteDirPath</code>. Note that while this method is able to find <code>fileName</code> ignoring case, it 
    * may not be able to do so if <code>absoluteDirPath</code> is in an incorrect case - that behavior is OS dependent. 
    * 
    * @param absoluteDirPath the absolute path of the parent directory of <code>fileName</code> (e.g. "/Users/me/foo") 
    * @param fileName the name of the file including extension that may or may not be the correct case 
    * (e.g. myfile.txt) 
    * @return an optional reference to the file if found, {@link Optional#empty()} will be returned if the file is not 
    * found 
    */ 
    public Optional<File> findFileIgnoreCase(String absoluteDirPath, final String fileName) { 

     File directory = new File(absoluteDirPath); 
     if (!directory.isDirectory()) { 
      throw new IllegalArgumentException("Directory '" + absoluteDirPath + "' isn't a directory."); 
     } 
     IOFileFilter caseInsensitiveFileNameFilter = new IOFileFilter() { 
      @Override 
      public boolean accept(File dir, String name) { 
       boolean isSameFile = fileName.equalsIgnoreCase(name); 
       return isSameFile; 
      } 

      @Override 
      public boolean accept(File file) { 
       String name = file.getName(); 
       boolean isSameFile = fileName.equalsIgnoreCase(name); 
       return isSameFile; 
      } 
     }; 
     Collection<File> foundFiles = FileUtils.listFiles(directory, caseInsensitiveFileNameFilter, null); 
     if (foundFiles == null || foundFiles.isEmpty()) { 
      return Optional.empty(); 
     } 
     if (foundFiles.size() > 1) { 
      throw new IllegalStateException(
        "More requirements needed to determine what to do with more than one file. Pick the closest match maybe?"); 
     } 
     // else exactly one file 
     File foundFile = foundFiles.iterator().next(); 
     return Optional.of(foundFile); 
    } 
} 

e qui ci sono alcuni casi di test:

import static org.junit.Assert.assertEquals; 
import static org.junit.Assert.assertFalse; 
import static org.junit.Assert.assertTrue; 

import java.io.File; 
import java.io.IOException; 
import java.util.Optional; 

import org.apache.commons.io.FileUtils; 
import org.apache.commons.lang.StringUtils; 
import org.junit.AfterClass; 
import org.junit.BeforeClass; 
import org.junit.Test; 

import com.google.common.io.Files; 

/** 
* Non-quite-unit tests for {@link CaseInsensitiveFileFinder} class. 
*/ 
public class CaseInsensitiveFileFinderTest { 

    private static String APPENDABLE_NEW_TMP_DIR_PATH; 

    /** 
    * Create the files with different cases. 
    * @throws IOException 
    */ 
    @BeforeClass 
    public static void setup() throws IOException { 
     File newTmpDir = Files.createTempDir(); 
     String newTmpDirPath = newTmpDir.getCanonicalPath(); 
     final String appendableNewTmpDirPath; 
     String fileSeparator = System.getProperty("file.separator"); 
     if (!newTmpDirPath.endsWith(fileSeparator)) { 
      appendableNewTmpDirPath = newTmpDirPath + fileSeparator; 
     } 
     else { 
      appendableNewTmpDirPath = newTmpDirPath; 
     } 
     CaseInsensitiveFileFinderTest.APPENDABLE_NEW_TMP_DIR_PATH = appendableNewTmpDirPath; 

     File foofileDotPng = new File(appendableNewTmpDirPath + "FOOFILE.PNG"); 
     Files.touch(foofileDotPng); 
     assertTrue(foofileDotPng.isFile()); 
     File barfileDotJpg = new File(appendableNewTmpDirPath + "BARFILE.JPG"); 
     Files.touch(barfileDotJpg); 
     assertTrue(barfileDotJpg.isFile()); 
    } 

    @AfterClass 
    public static void teardown() throws IOException { 
     File newTmpDir = new File(CaseInsensitiveFileFinderTest.APPENDABLE_NEW_TMP_DIR_PATH); 
     assertTrue(newTmpDir.isDirectory()); 
     // delete even though directory isn't empty 
     FileUtils.deleteDirectory(newTmpDir); 
    } 

    @Test 
    public void findFooFilePngUsingLowercase() throws IOException { 
     CaseInsensitiveFileFinder fileFinder = new CaseInsensitiveFileFinder(); 
     Optional<File> optFoundFile = fileFinder.findFileIgnoreCase(APPENDABLE_NEW_TMP_DIR_PATH, "foofile.png"); 
     assertTrue(optFoundFile.isPresent()); 
     File foundFile = optFoundFile.get(); 
     assertTrue(foundFile.isFile()); 
     assertEquals(APPENDABLE_NEW_TMP_DIR_PATH + "FOOFILE.PNG", foundFile.getCanonicalPath()); 
    } 

    @Test 
    public void findBarFileJpgUsingLowercase() throws IOException { 
     CaseInsensitiveFileFinder fileFinder = new CaseInsensitiveFileFinder(); 
     Optional<File> optFoundFile = fileFinder.findFileIgnoreCase(APPENDABLE_NEW_TMP_DIR_PATH, "barfile.jpg"); 
     assertTrue(optFoundFile.isPresent()); 
     File foundFile = optFoundFile.get(); 
     assertTrue(foundFile.isFile()); 
     assertEquals(APPENDABLE_NEW_TMP_DIR_PATH + "BARFILE.JPG", foundFile.getCanonicalPath()); 
    } 

    @Test 
    public void findFileThatDoesNotExist() { 
     CaseInsensitiveFileFinder fileFinder = new CaseInsensitiveFileFinder(); 
     Optional<File> optFoundFile = fileFinder.findFileIgnoreCase(APPENDABLE_NEW_TMP_DIR_PATH, "dne.txt"); 
     assertFalse(optFoundFile.isPresent()); 
    } 

    @Test 
    public void findFooFileUsingDirWithNoTrailingFileSeparator() throws IOException { 
     CaseInsensitiveFileFinder fileFinder = new CaseInsensitiveFileFinder(); 
     String newDirPathWithNoTrailingFileSep = StringUtils.chop(APPENDABLE_NEW_TMP_DIR_PATH); 
     Optional<File> optFoundFile = fileFinder.findFileIgnoreCase(newDirPathWithNoTrailingFileSep, "FOOFILE.PNG"); 
     assertTrue(optFoundFile.isPresent()); 
     File foundFile = optFoundFile.get(); 
     assertTrue(foundFile.isFile()); 
     assertEquals(APPENDABLE_NEW_TMP_DIR_PATH + "FOOFILE.PNG", foundFile.getCanonicalPath()); 
    } 
} 

Speranza che aiuta.

1

Invece di restituire t (l'estensione del file) restituire il file Object. In questo modo sei sicuro di avere il file corretto. Se non si desidera restituire l'oggetto file, restituire il nome del file con l'estensione.

public static File getPhotoFileExtension(int empKey){ 
    try{ 
     String[] types = {".jpg",".JPG",".png", ".PNG"}; 
     for(String t : types) 
     { 
      String path = "/"+Common.PHOTO_PATH + empKey + t; 
      File f = new File(Sessions.getCurrent().getWebApp() 
        .getRealPath(path)); 
      if(f.isFile()) 
       return f; 
     } 
    }catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 
0

Con quello Nima Thr Detto questo, si può fare ciò che si sta cercando con questo codice:

In Windows, se il file esiste, con ogni caso, restituirà true. Se il file non esiste, il nome canonico sarà lo stesso, quindi restituirà false.

Su Linux, se il file esiste con un caso diverso, il nome canonico restituirà questo nome diverso e il metodo restituirà true.

public static boolean fileExistsCaseInsensitive(String path) { 
    try { 
     File file = new File(path); 
     return file.exists() || !file.getCanonicalFile().getName().equals(file.getName()); 
    } catch (IOException e) { 
     return false; 
    } 
}