Как получить имя файла без расширения в Java?

Ответы:

429

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

import org.apache.commons.io.FilenameUtils;
String fileNameWithOutExt = FilenameUtils.removeExtension(fileNameWithExt);
Ульф Линдбек
источник
61
Вы также можете использовать FilenameUtils.getBasename для перехода от строки пути к имени файла без расширения.
Ян Дуркан
2
Самым простым является, конечно, запуск maven :-) В противном случае см .: commons.apache.org/io
Ульф Линдбек
8
Для тех, кто предпочитает гуаву, он тоже может это сделать . (В настоящее время я лично не очень
рад
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("[.][^.]+$", ""));
}
brianegge
источник
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
paxdiablo
источник
Какое расширение foo.tar.gz? Я понимаю, почему это .tar.gzбыло бы то, что вы хотели бы.
tchrist
5
@tchrist, foo.tar.gzэто версия gzip, foo.tarтак что вы также можете утверждать, что это gzбыло расширение. Все сводится к тому, как вы определяете расширение.
paxdiablo
2
что делать с файлами вроде .gitignore?
Михаил Нестеренко
Как вы знаете, имя класса в Java никогда не должно начинаться с маленькой буквы!
AnujKu
7
Если бы это было правилом, язык обеспечил бы его соблюдение. Поскольку это не так, это руководство, как бы сильно оно ни предлагалось. В любом случае, это совершенно не имеет отношения к вопросу и ответу.
paxdiablo
47

Вот порядок консолидированного списка по моим предпочтениям.

Использование Apache Commons

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

Liferay API

import com.liferay.portal.kernel.util.FileUtil; 
String fileName = FileUtil.stripExtension(file.getName());
Ом.
источник
42

Если ваш проект использует Guava (14.0 или новее), вы можете пойти с Files.getNameWithoutExtension().

(По сути, то же самое, что и в FilenameUtils.removeExtension()Apache Commons IO, как следует из ответа, получившего наибольшее количество голосов . Просто хотел бы отметить, что Guava делает то же самое. Лично я не хотел добавлять зависимость к Commons, что, по моему мнению, является чем-то вроде реликта) только из-за этого.)

Jonik
источник
2
на самом деле это больше похоже наFilenameUtils.getBaseName()
Angelo.Hannes
на самом деле guava - такая нестабильная библиотека, что я просто избегаю использовать ее везде, где могу. предпочитаю стабильную реликвию, чем эксперименты Гугеля
Слава
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.commons, я извлек ту же функциональность:

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

Хотя я очень верю в повторное использование библиотек, JAR org.apache.commons.io имеет размер 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от Apache 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

Для простоты используйте метод Java String.replaceAll () следующим образом:

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

Это также работает, когда fileNameWithExt включает полный путь.

GWC
источник
0

Вы можете использовать функцию разделения Java, чтобы отделить имя файла от расширения, если вы уверены, что в имени файла есть только одна точка для расширения.

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

поэтому split[0]вернет «test» и split [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строками.

Sksoni
источник
1
Это довольно плохая практика, чтобы реализовать такую ​​функциональность самостоятельно. На первый взгляд задача кажется предельно очевидной , но на практике вы столкнетесь с множеством исключительных ситуаций (например, нет .имени файла, или файл является резервной копией и имеет имя типа document.docx.backupи т. Д.). Гораздо надежнее использовать внешнюю библиотеку, которая решает все эти исключительные ситуации для вас.
ivstas
1
С другой стороны, добавление многих библиотек в ваш проект сделает его больше. Такие простые вещи, как это можно сделать сами.
Николас Тайлер
1
Никоим образом вы не должны делать это самостоятельно. Это сложно: файлы без расширения, но. в пути, пути ftp, косые черты в Windows и Unix, символические ссылки и т. д. Вы, безусловно, потерпите неудачу, и, пытаясь получить немного памяти, вы получите большую нестабильность. Как минимум, скопируйте источники установленного кода, если лицензии позволяют это.
Джонатан Наппи
Этот код выглядит как код от Амит Мишры, за исключением того пугающего 'if (! Str.contains ("."))'
Broken_Window
завершится с ошибкой в ​​следующем случае "/someFolder/some.other.folder/someFileWithoutExtention". Первое, что пришло в голову через 2 секунды ... Я уверен, что смогу придумать кучу других примеров.
Ньютопия