Як отримати ім'я файлу без розширення на Java?


Відповіді:


429

Якщо ви, як і я, краще скористаєтесь кодом бібліотеки, де вони, ймовірно, думали про всі особливі випадки, наприклад, що трапиться, якщо ви пропустите нуль або крапки в шляху, але не в назві файлу, ви можете використовувати наступне:

import org.apache.commons.io.FilenameUtils;
String fileNameWithOutExt = FilenameUtils.removeExtension(fileNameWithExt);

61
ви також можете використовувати FilenameUtils.getBasename, щоб перейти прямо від рядка шляху до імені файлу без розширення.
Ян Дуркан

2
Найпростіше - це звичайно біг maven :-) Інакше дивіться: commons.apache.org/io
Ulf Lindback

8
Для тих, хто віддає перевагу Гуаві, він може це зробити і . (У ці дні я особисто не дуже добре вкладаю залежність від Apache Commons, хоча історично ці бібліотеки були дуже корисні.)
Jonik

3
Хоча Guava і Commons-IO можуть запропонувати трохи додатково, ви здивуєтеся, скільки методів зручності вже включено до JDK 7 за допомогою java.nio.file.Filesта Path- наприклад, вирішення базових каталогів, однорядне копіювання / переміщення файлів, отримання лише імені файлу пр.
Дон Чедл,

3
@Lan Durkan наразі FilenameUtils.getBaseName з великою літерою N
Повільний Гаррі

153

Найпростіший спосіб - використовувати регулярний вираз.

fileNameWithOutExt = "test.xml".replaceFirst("[.][^.]+$", "");

Вищенаведений вираз видалить останню крапку, за якою слідують один або кілька символів. Ось базовий одиничний тест.

public void testRegex() {
    assertEquals("test", "test.xml".replaceFirst("[.][^.]+$", ""));
    assertEquals("test.2", "test.2.xml".replaceFirst("[.][^.]+$", ""));
}

11
Regex не такий простий у використанні, як бібліотечне рішення вище. Це працює, але дивлячись на код (без інтерпретації REGEX) не очевидно, що це робить.
Густаво Литовський

5
@GustavoLitovsky Android не постачається в комплекті org.apache.commons. Наскільки мені відомо, це єдиний спосіб зробити це в Android.
Ліам Джордж Бетсворт

1
/ * наступний регулярний вираз також видаляє шлях * / "/the/path/name.extension".replaceAll(".* зроблений". " ;
даггетт

1
Я б додав косої риски до другого класу символів, щоб переконатися, що вас не заштовхує такий шлях, як "/foo/bar.x/baz"
chrisinmtown

53

Дивіться таку програму тестування:

public class javatemp {
    static String stripExtension (String str) {
        // Handle null case specially.

        if (str == null) return null;

        // Get position of last '.'.

        int pos = str.lastIndexOf(".");

        // If there wasn't any '.' just return the string as is.

        if (pos == -1) return str;

        // Otherwise return the string, up to the dot.

        return str.substring(0, pos);
    }

    public static void main(String[] args) {
        System.out.println ("test.xml   -> " + stripExtension ("test.xml"));
        System.out.println ("test.2.xml -> " + stripExtension ("test.2.xml"));
        System.out.println ("test       -> " + stripExtension ("test"));
        System.out.println ("test.      -> " + stripExtension ("test."));
    }
}

який виводить:

test.xml   -> test
test.2.xml -> test.2
test       -> test
test.      -> test

Що таке розширення foo.tar.gz? Я бачу, чому .tar.gzбуло б те, чого ти хотів би.
tchrist

5
@tchrist, foo.tar.gzце gzipped версія, foo.tarщоб ви могли також стверджувати, що gzце розширення. Все зводиться до того, як ви визначаєте розширення.
paxdiablo

2
що робити з такими файлами .gitignore?
michael nesterenko

як ви знаєте, назва класу в java ніколи не повинна починатися з малої літери!
AnujKu

7
Якби це було правилом, мова застосовувала б це. Оскільки це не так, це правило, однак настійно пропонується. У будь-якому випадку, це абсолютно не має значення для питання та відповіді.
paxdiablo

47

Ось зведений перелік списків за моїм уподобанням.

Використання спільноти apache

import org.apache.commons.io.FilenameUtils;

String fileNameWithoutExt = FilenameUtils.getBaseName(fileName);

                           OR

String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);

Використання Google Guava (якщо ви її вже використовуєте)

import com.google.common.io.Files;
String fileNameWithOutExt = Files.getNameWithoutExtension(fileName);

Або за допомогою Core Java

1)

String fileName = file.getName();
int pos = fileName.lastIndexOf(".");
if (pos > 0 && pos < (fileName.length() - 1)) { // If '.' is not the first or last character.
    fileName = fileName.substring(0, pos);
}

2)

if (fileName.indexOf(".") > 0) {
   return fileName.substring(0, fileName.lastIndexOf("."));
} else {
   return fileName;
}

3)

private static final Pattern ext = Pattern.compile("(?<=.)\\.[^.]+$");

public static String getFileNameWithoutExtension(File file) {
    return ext.matcher(file.getName()).replaceAll("");
}

API Liferay

import com.liferay.portal.kernel.util.FileUtil; 
String fileName = FileUtil.stripExtension(file.getName());

42

Якщо у вашому проекті використовується Guava (14.0 або новіша версія), ви можете піти з цим Files.getNameWithoutExtension().

(По суті те саме, що в FilenameUtils.removeExtension()IO Apache Commons IO, як підказує відповідь найвищого голосу . Просто хотів би зазначити, що Гуава робить це теж. Особисто я не хотів додавати залежність до Commons - що, на мою думку, є трохи реліквією - саме через це.)


2
насправді це більше схоже наFilenameUtils.getBaseName()
Angelo.Hannes

насправді гуава - це така нестабільна в'язка, що я просто уникаю її використання, де можу. віддайте перевагу стійкій реліквії, ніж експерименти Гугеля
Слава

8

Нижче наведено посилання з https://android.googlesource.com/platform/tools/tradefederation/+/master/src/com/android/tradefed/util/FileUtil.java

/**
 * Gets the base name, without extension, of given file name.
 * <p/>
 * e.g. getBaseName("file.txt") will return "file"
 *
 * @param fileName
 * @return the base name
 */
public static String getBaseName(String fileName) {
    int index = fileName.lastIndexOf('.');
    if (index == -1) {
        return fileName;
    } else {
        return fileName.substring(0, index);
    }
}

1
Приємна інформація, але користувачі знайте про випадки типу ".htaccess", де цей метод повернеться "".
Маркус Шульте

6

Якщо вам не подобається імпортувати повний апарат apache.com, я витягнув таку ж функціональність:

public class StringUtils {
    public static String getBaseName(String filename) {
        return removeExtension(getName(filename));
    }

    public static int indexOfLastSeparator(String filename) {
        if(filename == null) {
            return -1;
        } else {
            int lastUnixPos = filename.lastIndexOf(47);
            int lastWindowsPos = filename.lastIndexOf(92);
            return Math.max(lastUnixPos, lastWindowsPos);
        }
    }

    public static String getName(String filename) {
        if(filename == null) {
            return null;
        } else {
            int index = indexOfLastSeparator(filename);
            return filename.substring(index + 1);
        }
    }

    public static String removeExtension(String filename) {
        if(filename == null) {
            return null;
        } else {
            int index = indexOfExtension(filename);
            return index == -1?filename:filename.substring(0, index);
        }
    }

    public static int indexOfExtension(String filename) {
        if(filename == null) {
            return -1;
        } else {
            int extensionPos = filename.lastIndexOf(46);
            int lastSeparator = indexOfLastSeparator(filename);
            return lastSeparator > extensionPos?-1:extensionPos;
        }
    }
}

4

Хоча я дуже вірую у повторне використання бібліотек, org.apache.commons.io JAR становить 174 КБ, що помітно велике для мобільного додатка.

Якщо ви завантажите вихідний код і подивіться на їх клас FilenameUtils, ви можете побачити, що тут є багато додаткових утиліт, і він справляється із шляхами Windows та Unix, що все чудово.

Однак, якщо ви просто хочете пару статичних методів корисності для використання з контурами стилю Unix (з роздільником "/"), ви можете знайти код нижче корисним.

removeExtensionМетод зберігає решту шляху разом з ім'ям файлу. Існує також подібне getExtension.

/**
 * Remove the file extension from a filename, that may include a path.
 * 
 * e.g. /path/to/myfile.jpg -> /path/to/myfile 
 */
public static String removeExtension(String filename) {
    if (filename == null) {
        return null;
    }

    int index = indexOfExtension(filename);

    if (index == -1) {
        return filename;
    } else {
        return filename.substring(0, index);
    }
}

/**
 * Return the file extension from a filename, including the "."
 * 
 * e.g. /path/to/myfile.jpg -> .jpg
 */
public static String getExtension(String filename) {
    if (filename == null) {
        return null;
    }

    int index = indexOfExtension(filename);

    if (index == -1) {
        return filename;
    } else {
        return filename.substring(index);
    }
}

private static final char EXTENSION_SEPARATOR = '.';
private static final char DIRECTORY_SEPARATOR = '/';

public static int indexOfExtension(String filename) {

    if (filename == null) {
        return -1;
    }

    // Check that no directory separator appears after the 
    // EXTENSION_SEPARATOR
    int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);

    int lastDirSeparator = filename.lastIndexOf(DIRECTORY_SEPARATOR);

    if (lastDirSeparator > extensionPos) {
        LogIt.w(FileSystemUtil.class, "A directory separator appears after the file extension, assuming there is no file extension");
        return -1;
    }

    return extensionPos;
}

1
public static String getFileExtension(String fileName) {
        if (TextUtils.isEmpty(fileName) || !fileName.contains(".") || fileName.endsWith(".")) return null;
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    public static String getBaseFileName(String fileName) {
        if (TextUtils.isEmpty(fileName) || !fileName.contains(".") || fileName.endsWith(".")) return null;
        return fileName.substring(0,fileName.lastIndexOf("."));
    }

1

Використовується найпростіший спосіб отримати ім'я з відносного шляху або повного шляху

import org.apache.commons.io.FilenameUtils; FilenameUtils.getBaseName(definitionFilePath)


0

Ви можете розділити його на "." а в індексі 0 - ім'я файлу, а на 1 - розширення, але я схиляюсь до найкращого рішення з FileNameUtils від apache.commons-io, як це було зазначено у першій статті. Її не потрібно видаляти, але достатньо:

String fileName = FilenameUtils.getBaseName("test.xml");


0

Використання FilenameUtils.removeExtensionз AOche Commons IO

Приклад:

Ви можете вказати повне ім'я шляху або лише ім'я файлу .

String myString1 = FilenameUtils.removeExtension("helloworld.exe"); // returns "helloworld"
String myString2 = FilenameUtils.removeExtension("/home/abc/yey.xls"); // returns "yey"

Сподіваюся, це допомагає ..


Це вже у прийнятій відповіді, в чому сенс цієї публікації?
Том

0

Вільний спосіб:

public static String fileNameWithOutExt (String fileName) {
    return Optional.of(fileName.lastIndexOf(".")).filter(i-> i >= 0)
            .map(i-> fileName.substring(0, i)).orElse(fileName);
}

0

Зберігаючи це просто, використовуйте метод String.replaceAll () Java як слід:

String fileNameWithExt = "test.xml";
String fileNameWithoutExt
   = fileNameWithExt.replaceAll( "^.*?(([^/\\\\\\.]+))\\.[^\\.]+$", "$1" );

Це також працює, коли fileNameWithExt включає повністю кваліфікований шлях.


0

Ви можете використовувати java split функцію, щоб розділити ім'я файлу від розширення, якщо ви впевнені, що у назві файлу є лише одна крапка, яка для розширення.

File filename = new File('test.txt'); File.getName().split("[.]");

тож split[0]повернеться "тест" і спліт [1] поверне "txt"


-3

Спробуйте наведений нижче код. Використання основних функцій Java. Він піклується про Strings з розширенням та без розширення (без '.'символу). Справа множини '.'також висвітлюється.

String str = "filename.xml";
if (!str.contains(".")) 
    System.out.println("File Name=" + str); 
else {
    str = str.substring(0, str.lastIndexOf("."));
    // Because extension is always after the last '.'
    System.out.println("File Name=" + str);
}

Ви можете адаптувати його до роботи зі nullструнами.


1
Досить погана практика самостійно реалізувати такий функціонал. На перший погляд завдання здається надзвичайно очевидним , але на практиці ви зіткнетеся з безліччю виняткових ситуацій (як, наприклад, .у імені файлу немає , або файл - це резервна копія та має ім’я на зразок document.docx.backupтощо). Набагато надійніше використовувати зовнішню бібліотеку, яка займається всіма винятковими ситуаціями для вас.
ivstas

1
З іншого боку, додавання багатьох бібліотек до вашого проекту зробить його більшим. Тож такі прості речі, як це, можна зробити самим.
Ніколя Тайлер

1
Ні в якому разі не слід робити це самостійно. Це важко: файли без розширення, але. у шляху, ftp шляхи, косою рисою вікон та Unix, символічними посиланнями тощо ... Ви неодмінно зазнаєте невдачі і, намагаючись набрати трохи пам'яті, ви оголосите багато нестабільності. Як мінімум копіюйте джерела встановленого коду, якщо ліцензії це дозволяють.
Джонатан Наппе

Цей код схожий на той, від Аміта Мішри, за винятком того, що залякує 'if (! Str.contains ("."))'
Broken_Window

не вдасться у такому випадку "/someFolder/some.other.folder/someFileWithoutExtention". Перше, що з’явилося на увазі через 2 секунди. Я впевнений, що міг би придумати багато інших прикладів.
Ньютопіан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.