2016-01-05 8 views
13

Ich benutze diese Funktion, um zu erkennen, ob meine Datei existiert oder nicht. Während ich ein Bild als .jpg, .JPG, .png und .PNG gespeichert habe. Aber es wird immer .jpg oder .png als wahr zurückgegeben, auch wenn die reale Datei die Erweiterung .JPG oder .PNG hat.Java File existiert Case sensitive .jpg und .JPG

Nachdem ich es auf meiner Webseite gerendert habe, gibt es einen Fehler aus "Fehler beim Laden der Ressource: Der Server reagierte mit dem Status 404 (Not Found)".

+1

Nein, diese Frage fragt, wie Abc.txt von abc.txt geladen wird. Ich frage nach, wie man erkennt, ob abc.txt oder abc.TXT existiert. –

+0

Jeder Mitarbeiter hat ein Bild, aber sie speichern in verschiedenen Erweiterungen jpg JPG PNG oder PNG. aber meine Funktion gibt immer jpg oder png zurück, während die Extension ist JPG oder PNG –

+0

@John Hascal immer noch Kleinbuchstaben Extension –

Antwort

16

Sie möchten also die echten Namen von Dateien, die in Ihrem Dateisystem gespeichert sind. Lets Bildgebung haben wir folgende Wege:

  • auf Linux: mit ext4/testFolder/test.PnG
  • auf Windows- mit NTFS (die nicht Fall ist (die Groß- und Kleinschreibung) empfindlich) c:\testFolder\test.PnG

Nr w können einige Java File Objekte zu jeder Bilddatei erstellen.

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

Ihr Problem ist, dass alle Anrufe von File wie File.exists auf die java.io.FileSystem Klasse umgeleitet werden, die von der JVM realen Betriebssystemaufrufe des Dateisystems darstellt. Sie können also unter Windows nicht zwischen test.PNG und test.png unterscheiden. Auch Windows selbst nicht.

Aber sogar unter Windows jede Datei hat einen definierten Namen im Dateisystem, der zum Beispiel sein könnte: test.PnG. Sie sehen dies in Ihrer Windows Explorer oder in der Befehlszeile, wenn Sie dir c:\testFolder eingeben.

Also, was Sie in Java tun können, ist die File.list Methode auf der parent directory, die in der Betriebssystemliste Anruf für alle Dateien in diesem Verzeichnis mit ihren echten Namen führt.

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

oder wenn Sie es vorziehen File Objekte

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

Hiermit können Sie Ihre eigene exists Methode schreiben, die Groß- und Kleinschreibung auf allen Betriebssystemen ist

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

es wie folgt verwendet:

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



EDIT: Ich muss zugeben, dass ich falsch lag. Es gibt eine Möglichkeit, den richtigen Namen einer Datei zu erhalten. Ich habe immer die Methode File.getCanonicalPath übersehen.
Wieder unser Beispiel: Wir haben diese Datei c:\testFolder\test.PnG.

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

Mit diesem Wissen können Sie ohne Iterieren alle Dateien ein einfaches Testverfahren für die Groß- und Kleinschreibung Erweiterung schreiben.

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; 
} 

es wie folgt verwendet:

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

'File.getCanonicalPath()' ist, zumindest mit meinem Setup, kein zuverlässiger Weg, um den echten Dateinamen zu erhalten. Ich habe eine kleine Klasse geschrieben, die wiederholt das Ergebnis von 'File.getCanonicalPath()' auf die Eclipse-Konsole ausgibt. Während das Programm ausgeführt wird, führt das Umbenennen der Datei "abc.txt" in "Abc.txt" dazu, dass 'getCanonicalPath()' immer noch "abc" zurückgibt.txt ", bis ich das Programm/JVM neu starte. Mein Setup ist JDK 6u45 und Windows 10. Ich musste eine Lösung basierend auf dem Ausdruck' ArrayUtils.contains (parentFile.list(), realFileName) 'verwenden. –

3

Wenn Sie für eine Funktion suchen, der in jeder Plattform Existenz einer Datei bestimmen kann und die Groß-; dies sollte es tun:

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

Ich begann mit diesem um ein wenig durcheinander, weil ich nicht benutzt habe IOFileFilter Apache vor und dachte, dass ich diese Lösung als eine Chance, mit ihm ein wenig zu spielen hinzufügen würde. Hier

ist der Code:

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); 
    } 
} 

Und hier sind einige Testfälle:

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()); 
    } 
} 

Hoffnung, das hilft.

1

Anstatt t (die Dateierweiterung) zurückzugeben, geben Sie die Datei Object zurück. Auf diese Weise können Sie sicher sein, dass Sie die richtige Datei haben. Wenn Sie das Dateiobjekt nicht zurückgeben möchten, geben Sie den Dateinamen mit der Erweiterung zurück.

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

Mit diesem Nima Thr sagte, können Sie tun, was Sie für mit diesem Code suchen:

Wenn unter Windows die Datei vorhanden ist, mit jedem Fall wird es wahr zurück. Wenn die Datei nicht existiert, ist der kanonische Name gleich, daher wird false zurückgegeben.

Wenn unter Linux die Datei in einem anderen Fall existiert, gibt der kanonische Name diesen anderen Namen zurück, und die Methode gibt true zurück.

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; 
    } 
}