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


177

Який найефективніший спосіб обрізати суфікс на Java, наприклад:

title part1.txt
title part2.html
=>
title part1
title part2

2
ефективний код розумний - це те, на що я сподіваюсь, а не CPU мудрий
— mkoryak

3
Він не запитував, як це зробити, він запитував, який найефективніший спосіб. Я прийшов сюди шукати те саме.
— Едвард Фолк

Відповіді:


285

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

У цьому випадку я рекомендую використовувати FilenameUtils.removeExtension () від AOche Commons IO


7
Абсолютно ударив.
— Джошуа Пінтер

6
Для 95% проектів це має бути прийнятою відповіддю. Переписування коду, як це, є першопричиною багатьох головних болів!
— Карстен Гофман

1
Просто додайте наступний рядок у gradle, щоб додати залежність: - компілювати 'commons-io: commons-io: 2.6'
— Deepak Sharma

Приклад, будь ласка.
— John ktejik

8
Якщо у вас є проект Apache Commons I / O вже у вашому проекті, це правильно. Але якщо це все, що вам потрібно від цього, ви додасте (принаймні) 2,5 Мб мертвої ваги до свого проекту для чогось, що легко зробити одним рядком.
— foo

227
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метод IO Apache Commons .

Щоб відтворити її поведінку, я написав кілька тестів, які повинен виконати новий метод, які є наступними:

Ім'я файлу шляху
-------------- --------
a / b / cc
a / b / c.jpg c
a / b / c.jpg.jpg c.jpg

аб / куб
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

Результати - це бажані результати, викладені в тесті, який повинен виконати метод.


4
Чудова відповідь. Чи є певна причина, чому ви використовуєте, System.getProperty("file.separator")а не просто File.separator?
— халірутан

2
Слово попередження: Це рішення також видаляє попередній шлях, а не лише розширення, на відміну від методу IO Apache Commons.
— DHa

3
Схоже, це не вдасться/path/to/.htaccess
— Кузеко

17

BTW, у моєму випадку, коли я хотів швидке рішення про видалення конкретного розширення, це приблизно те, що я зробив:

  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('.'));

4
Ні, їх може бути більше, ніж "." you want 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);
}

Це хитрі питання? : с

Я не можу придумати швидший спосіб атм.


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

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: \ Користувачі \ mroh004.COM \ Документи \ Тест \ Тест", а ні
   "Тест"

5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();

3
Навпроти того, що було запропоновано, і немає необхідності пропускати довжину, просто використовуйте одну аргументальну підрядку

4

Використовуйте регулярний вираз. Цей замінює останню крапку і все після неї.

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

Ви також можете створити об'єкт "Шаблон", якщо ви хочете попередньо компілювати регулярний вираз.


1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");

Потрібно розділити на "\\.""." є спеціальним для регексу.
— Компас

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

Починаючи з кінця до "." потім викличте підрядку.

Редагувати: Можливо, це не гольф, але це ефективно :)


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

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


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" в "а" і ".htaccess" в порожнечу. Ця функція працює з Strings, тому імена файлів можуть бути недійсними, але все ж можуть бути довжиною 0, швидше перевірте, чи варто це перед тим, як розбирати символи. З повагою
— Олексій
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.