Подтвердить что ты не робот

Файл Java существует с учетом регистра .jpg и .JPG

Я использую эту функцию, чтобы определить, существует ли мой файл или нет. Хотя у меня есть изображение, хранящееся как .jpg,.JPG,.png и .PNG. Но он всегда возвращает .jpg или .png как истинный, даже если реальный файл имеет расширение .JPG или .PNG.

После того, как я отрисую его на мою веб-страницу, он выдает сообщение об ошибке "Не удалось загрузить ресурс: сервер ответил со статусом 404 (не найден)".

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 "";
}
4b9b3361

Ответ 1

Итак, вы хотите получить реальные имена файлов, хранящихся в вашей файловой системе. Для получения изображений мы имеем следующие пути:

  • on Linux:, используя ext4 (чувствительный к регистру) /testFolder/test.PnG
  • в Windows с помощью NTFS (не) c:\testFolder\test.PnG

Теперь создадим несколько объектов Java File для каждого файла изображения.

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

Ваша проблема в том, что все вызовы File как File.exists перенаправляются в класс java.io.FileSystem, который представляет реальные вызовы операционной системы вашей файловой системы с помощью JVM. Таким образом, вы не можете отличить Windows Machines между test.PNG и test.PNG. Ни сама Windows.

Но даже в Windows каждый файл имеет определенное имя в файловой системе, которое может быть, например: test.PNG. Вы увидите это в своем Windows Explorer или в командной строке, если вы наберете dir c:\testFolder.

Итак, что вы можете сделать в Java, используйте метод File.list в parent directory, который приводит к вызову списка операционной системы для всех файлов в этом каталоге с их настоящими именами.

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

или если вы предпочитаете File Объекты

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

Вы можете использовать это, чтобы написать свой собственный метод exists, чувствительный к регистру во всех операционных системах

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

Используйте его следующим образом:

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



EDIT: Я должен признать, что я был неправ. Существует способ получить реальное имя файла. Я всегда пропускал метод File.getCanonicalPath.
Опять наш пример: у нас есть файл c:\testFolder\test.PnG.

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

С помощью этих знаний вы можете написать простой метод тестирования для чувствительного к регистру расширения без повторения всех файлов.

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

Используйте его следующим образом:

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

Ответ 2

Если вы ищете функцию, которая на любой платформе может определять наличие файла и учитывает регистр; это должно сделать это:

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

Ответ 3

Я начал немного перебираться с этим, потому что раньше я не использовал Apache IOFileFilter и думал, что добавлю это решение в качестве шанса немного поиграть с ним.

Вот код:

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

И вот несколько тестовых примеров:

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

Надеюсь, что это поможет.

Ответ 4

Вместо возврата t (расширение файла) верните файл Object. Таким образом, вы уверены, что у вас есть правильный файл. Если вы не хотите возвращать объект файла, верните имя файла с расширением.

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

Ответ 5

С помощью этого NiMa Thr вы можете делать то, что ищете, с помощью этого кода:

В Windows, если файл существует, в любом случае он вернет true. Если файл не существует, каноническое имя будет таким же, поэтому оно вернет false.

В Linux, если файл существует с другим случаем, каноническое имя вернет это другое имя, и метод вернет 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;
    }
}