Як обрізати розширення файлу з рядка на 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.