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

177

Какой самый эффективный способ обрезать суффикс в Java, например так:

title part1.txt
title part2.html
=>
title part1
title part2
О, мой бог
источник
2
Надеюсь, эффективный код - это то, что вы имеете в виду, а не процессор
mkoryak
3
Он не спрашивал, как это сделать, он спрашивал, что является наиболее эффективным способом. Я пришел сюда в поисках того же.
Эдвард Фальк

Ответы:

285

Это тот код, который мы не должны делать сами. Используйте библиотеки для мирских вещей, спасите свой мозг для тяжелых вещей.

В этом случае я рекомендую использовать FilenameUtils.removeExtension () из Apache Commons IO

skaffman
источник
7
Абсолютно грохнуть.
Джошуа Пинтер
6
Для 95% проектов это должен быть принятый ответ. Переписывание такого кода является основной причиной многих головных болей!
Карстен Хоффманн
1
Просто добавьте следующую строку в gradle для добавления зависимости: - скомпилируйте 'commons-io: commons-io: 2.6'
Deepak Sharma
пример пожалуйста.
Джон Ктехик
8
Если у вас уже есть Apache Commons I / O в вашем проекте, это правильно. Но если это все, что вам нужно от этого, вы добавляете (как минимум) 2,5 МБ собственного веса в свой проект для чего-то, что можно легко сделать с помощью одной строки.
Foo
229
str.substring(0, str.lastIndexOf('.'))
Светлана Максимчук
источник
8
Это должно быть присвоено новой переменной, так как str не изменяется.
Натан Фегер
51
Обращайтесь с ним осторожно: оно выдаст вам исключение, если у имени файла нет суффикса.
Андреас Долк
24
что насчет archive.tar.bz2?
Антонио
20
if(str.contains(".")) str.substring(0, str.lastIndexOf('.'))
Николас Тайлер
6
if (str! = null && str.contains (".")) str.substring (0, str.lastIndexOf ('.')). FilenameUtils - еще одна зависимость, и она не всегда доступна
ocramot
88

Поскольку использование String.substringи String.lastIndexв одной строке хорошо, есть некоторые проблемы с точки зрения возможности справиться с определенными путями к файлам.

Возьмем для примера следующий путь:

a.b/c

Использование однострочника приведет к:

a

Это неверно

Результат должен был быть c, но поскольку у файла отсутствовало расширение, но путь имел каталог с .именем в имени, метод с одной строкой был обманут, чтобы дать часть пути в качестве имени файла, что не является правильным.

Нужны чеки

Вдохновленный ответом Скаффмана , я взглянул на FilenameUtils.removeExtensionметод Apache Commons IO .

Чтобы воссоздать его поведение, я написал несколько тестов, которые должен выполнить новый метод, а именно:

Путь Имя файла
-------------- --------
A / B / куб.см
a / b / c.jpg c
a / b / c.jpg.jpg c.jpg

AB / куб.см
ab / c.jpg c
ab / c.jpg.jpg c.jpg

куб.см
c.jpg c
c.jpg.jpg c.jpg

(И это все, что я проверял - возможно, есть другие проверки, которые я должен пропустить.)

Реализация

Ниже приведена моя реализация removeExtensionметода:

public static String removeExtension(String s) {

    String separator = System.getProperty("file.separator");
    String filename;

    // Remove the path upto the filename.
    int lastSeparatorIndex = s.lastIndexOf(separator);
    if (lastSeparatorIndex == -1) {
        filename = s;
    } else {
        filename = s.substring(lastSeparatorIndex + 1);
    }

    // Remove the extension.
    int extensionIndex = filename.lastIndexOf(".");
    if (extensionIndex == -1)
        return filename;

    return filename.substring(0, extensionIndex);
}

Запуск этого removeExtensionметода с вышеуказанными тестами дает результаты, перечисленные выше.

Метод был протестирован с использованием следующего кода. Поскольку это было выполнено в Windows, разделитель пути - это символ, \который должен быть экранирован \при использовании в качестве части Stringлитерала.

System.out.println(removeExtension("a\\b\\c"));
System.out.println(removeExtension("a\\b\\c.jpg"));
System.out.println(removeExtension("a\\b\\c.jpg.jpg"));

System.out.println(removeExtension("a.b\\c"));
System.out.println(removeExtension("a.b\\c.jpg"));
System.out.println(removeExtension("a.b\\c.jpg.jpg"));

System.out.println(removeExtension("c"));
System.out.println(removeExtension("c.jpg"));
System.out.println(removeExtension("c.jpg.jpg"));

Результаты были:

c
c
c.jpg
c
c
c.jpg
c
c
c.jpg

Результаты - это желаемые результаты, изложенные в тесте, который должен выполнить метод.

coobird
источник
4
Отличный ответ. Есть ли конкретная причина, почему вы используете, System.getProperty("file.separator")а не только File.separator?
Халирутан
2
Предупреждение: это решение также удаляет предыдущий путь, а не только расширение, в отличие от метода ввода-вывода Apache Commons.
DHa
3
Похоже, что это не удастся для/path/to/.htaccess
Kuzeko
17

Кстати, в моем случае, когда я хотел быстрое решение для удаления определенного расширения, это примерно то, что я сделал:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;
Эдвард Фальк
источник
16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));
Jherico
источник
4
Нет, может быть более одного '.'; Вы хотите lastIndexOf ('.')
Адам Яскевич
-1 за то, что не использовал метод, который, как я думал, вы использовали. Это теперь +0 от меня. Измени это быстро! ;)
Майкл Майерс
7
String fileName="foo.bar";
int dotIndex=fileName.lastIndexOf('.');
if(dotIndex>=0) { // to prevent exception if there is no dot
  fileName=fileName.substring(0,dotIndex);
}

Это вопрос с подвохом? :п

Я не могу думать о более быстром способе.

Huxi
источник
7

Используйте метод в com.google.common.io.Filesклассе, если ваш проект уже зависит от основной библиотеки Google. Метод, который вам нужен getNameWithoutExtension.

Тоби
источник
Почему кто-то против моего ответа ??
Тоби
Обратите внимание, что при этом возвращается только базовое имя, поэтому путь также удаляется: google.github.io/guava/releases/19.0/api/docs/com/google/common/…
thSoft
6

Вы можете попробовать эту функцию, очень простой

public String getWithoutExtension(String fileFullPath){
    return fileFullPath.substring(0, fileFullPath.lastIndexOf('.'));
}
Shantonu
источник
5

Я нашел ответ CoolBird особенно полезным.

Но я изменил последний результат заявления на:

if (extensionIndex == -1)
  return s;

return s.substring(0, lastSeparatorIndex+1) 
         + filename.substring(0, extensionIndex);

как я хотел, чтобы было возвращено полное имя пути.

Так что «C: \ Users \ mroh004.COM \ Documents \ Test \ Test.xml» становится 
   "C: \ Users \ mroh004.COM \ Documents \ Test \ Test", а не
   "Тест"
MXRO
источник
5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();
Александр
источник
3
Напротив того, что было задано, и нет необходимости передавать длину, просто используйте одну подстроку arg
4

Используйте регулярное выражение. Эта заменяет последнюю точку и все после нее.

String baseName = fileName.replaceAll("\\.[^.]*$", "");

Вы также можете создать объект Pattern, если хотите предварительно скомпилировать регулярное выражение.

Стивен Спунгин
источник
1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");
Mahdak
источник
Нужно разделить на "\\.""." специально для регулярных выражений.
Компас
1

создайте новый файл с путем строкового изображения

String imagePath;
File test = new File(imagePath);
test.getName();
test.getPath();
getExtension(test.getName());


public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }
Правин Бхосале
источник
1

org.apache.commons.io.FilenameUtils версии 2.4 дает следующий ответ

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

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

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

public static final char EXTENSION_SEPARATOR = '.';
private static final char UNIX_SEPARATOR = '/';
private static final char WINDOWS_SEPARATOR = '\\';
Кто-то где-то
источник
1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }
сверхновая звезда
источник
0

Я бы сделал так:

String title_part = "title part1.txt";
int i;
for(i=title_part.length()-1 ; i>=0 && title_part.charAt(i)!='.' ; i--);
title_part = title_part.substring(0,i);

Начиная с конца и до "." затем вызовите подстроку.

Изменить: не может быть гольф, но это эффективно :)

fmsf
источник
7
Это в основном то, что делает lastIndexOf в любом случае; зачем изобретать велосипед?
Майкл Майерс
Для удовольствия и быть немного описательным. только то. (и я забыл о lastIndexOf, когда писал это)
fmsf
0

Принимая во внимание сценарии, в которых отсутствует расширение файла или имеется более одного расширения файла

пример Имя файла: файл | file.txt | file.tar.bz2

/**
 *
 * @param fileName
 * @return file extension
 * example file.fastq.gz => fastq.gz
 */
private String extractFileExtension(String fileName) {
    String type = "undefined";
    if (FilenameUtils.indexOfExtension(fileName) != -1) {
        String fileBaseName = FilenameUtils.getBaseName(fileName);
        int indexOfExtension = -1;
        while (fileBaseName.contains(".")) {
            indexOfExtension = FilenameUtils.indexOfExtension(fileBaseName);
            fileBaseName = FilenameUtils.getBaseName(fileBaseName);
        }
        type = fileName.substring(indexOfExtension + 1, fileName.length());
    }
    return type;
}
Choesang
источник
0
String img = "example.jpg";
// String imgLink = "http://www.example.com/example.jpg";
URI uri = null;

try {
    uri = new URI(img);
    String[] segments = uri.getPath().split("/");
    System.out.println(segments[segments.length-1].split("\\.")[0]);
} catch (Exception e) {
    e.printStackTrace();
}

Это выведет пример для img и imgLink

urs86ro
источник
0
public static String removeExtension(String file) {
    if(file != null && file.length() > 0) {
        while(file.contains(".")) {
            file = file.substring(0, file.lastIndexOf('.'));
        }
    }
    return file;
}
Алексей
источник
Это преобразует «a.jpg.jpg» в «a» вместо (правильного) «a.jpg». Какой цели служит file.length() > 0проверка?
Клаус Гюттер
Главный вопрос был «как удалить расширение?», Так что да, его преобразование «a.txt.zip» в «a» и «.htaccess» в пустоту. Эта функция работает со строками, поэтому имена файлов могут быть не нулевыми, но при этом иметь длину 0, быстрее проверяйте, стоит ли оно того, перед анализом символов. С уважением.
Алексей