Jak przyciąć rozszerzenie pliku z ciągu w Javie?


177

Jaki jest najbardziej skuteczny sposób przycinania sufiksu w Javie, na przykład:

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

2
wydajny kod, mam nadzieję, że to masz na myśli, a nie procesor
— mkoryak

3
Nie pytał, jak to zrobić, pytał, jaki jest najbardziej efektywny sposób. Przyszedłem tutaj, szukając tego samego.
— Edward Falk

Odpowiedzi:


285

To jest rodzaj kodu, którego sami nie powinniśmy robić. Korzystaj z bibliotek do zwykłych rzeczy, zachowaj mózg na trudne rzeczy.

W tym przypadku polecam użycie FilenameUtils.removeExtension () z Apache Commons IO


7
Absolutnie strzał w dziesiątkę.
— Joshua Pinter,

6
W przypadku 95% projektów powinna to być akceptowana odpowiedź. Przepisanie kodu w ten sposób jest główną przyczyną wielu bólów głowy!
— Carsten Hoffmann

1
Po prostu dodaj następującą linię w gradle, aby dodać zależność: - kompiluj 'commons-io: commons-io: 2.6'
— Deepak Sharma

przykład proszę.
— john ktejik

8
Jeśli masz już Apache Commons I / O w swoim projekcie, to prawda. Ale jeśli to wszystko, czego potrzebujesz, dodajesz (co najmniej) 2,5 MB masy własnej do swojego projektu, aby coś, co można łatwo zrobić za pomocą jednej linii.
— foo

227
str.substring(0, str.lastIndexOf('.'))

8
Należy to przypisać do nowej zmiennej, ponieważ str nie jest modyfikowany.
— Nathan Feger

51
Postępuj ostrożnie: wyrzuci wyjątek, jeśli nazwa pliku nie ma sufiksu.
— Andreas Dolk

24
a co z archive.tar.bz2?
— Antonio

20
if(str.contains(".")) str.substring(0, str.lastIndexOf('.'))
— Nicolas Tyler

6
if (str! = null && str.contains (".")) str.substring (0, str.lastIndexOf ('.')). FilenameUtils to kolejna zależność, która nie zawsze jest dostępna
— ocramot

88

Ponieważ używanie String.substringi String.lastIndexw jednowierszowym jest dobre, istnieją pewne problemy związane z możliwością radzenia sobie z określonymi ścieżkami plików.

Weźmy na przykład następującą ścieżkę:

a.b/c

Użycie jednowierszowego spowoduje:

a

To jest niepoprawne.

Wynik powinien być c, ale ponieważ plik nie miał rozszerzenia, ale ścieżka miała katalog z .w nazwie, metoda jednowierszowa została oszukana i podała część ścieżki jako nazwę pliku, co nie jest poprawne.

Potrzeba czeków

Zainspirowany odpowiedzią skaffmana , przyjrzałem się FilenameUtils.removeExtensionmetodzie Apache Commons IO .

Aby odtworzyć jego zachowanie, napisałem kilka testów, jakie powinna spełniać nowa metoda, a są to:

Nazwa pliku ścieżki
-------------- --------
a / b / cc
a / b / c.jpg c
a / b / c.jpg.jpg c.jpg

ab / cc
ab / c.jpg c
ab / c.jpg.jpg c.jpg

cc
c.jpg c
c.jpg.jpg c.jpg

(I to wszystko, co sprawdziłem - prawdopodobnie są inne kontrole, które powinny być na miejscu, o których przeoczyłem).

Implementacja

Oto moja implementacja removeExtensionmetody:

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

Uruchomienie tej removeExtensionmetody z powyższymi testami daje wyniki wymienione powyżej.

Metoda została przetestowana z następującym kodem. Ponieważ zostało to uruchomione w systemie Windows, separatorem ścieżki jest znak, \który musi zostać poprzedzony znakiem a, \gdy jest używany jako część Stringliterału.

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

Wyniki były następujące:

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

Wyniki to pożądane wyniki przedstawione w badaniu, które metoda powinna spełniać.


4
Świetna odpowiedź. Czy jest jakiś konkretny powód, dla którego używasz, System.getProperty("file.separator")a nie tylko File.separator?
— halirutan

2
Słowo ostrzeżenia: to rozwiązanie usuwa również poprzednią ścieżkę, a nie tylko rozszerzenie, w przeciwieństwie do metody Apache Commons IO.
— DHa

3
Wygląda na to, że to się nie powiedzie dla/path/to/.htaccess
— Kuzeko

17

Swoją drogą w moim przypadku, gdy chciałem szybko rozwiązać problem usunięcia konkretnego rozszerzenia, tak w przybliżeniu zrobiłem:

  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
Nie, może być więcej niż jeden znak „.”; chcesz lastIndexOf ('.')
— Adam Jaskiewicz

-1 za niestosowanie metody, o której myślałem, że używasz. To teraz łącznie +0 ode mnie. Zmień to szybko! ;)
— Michael Myers

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

Czy to podchwytliwe pytanie? : p

Nie mogę wymyślić szybszego bankomatu.



6

możesz wypróbować tę funkcję, bardzo podstawową

public String getWithoutExtension(String fileFullPath){
    return fileFullPath.substring(0, fileFullPath.lastIndexOf('.'));
}

5

Znalazłem odpowiedź coolbird jest szczególnie przydatna.

Ale zmieniłem ostatnie stwierdzenia wyniku na:

if (extensionIndex == -1)
  return s;

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

ponieważ chciałem zwrócić pełną nazwę ścieżki.

Tak więc „C: \ Users \ mroh004.COM \ Documents \ Test \ Test.xml” staje się 
   „C: \ Users \ mroh004.COM \ Documents \ Test \ Test”, a nie
   "Test"

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

3
W przeciwieństwie do tego, o co pytano i nie ma potrzeby

4

Użyj wyrażenia regularnego. Ten zastępuje ostatnią kropkę i wszystko po niej.

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

Możesz także utworzyć obiekt Pattern, jeśli chcesz wstępnie skompilować wyrażenie regularne.


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

Musisz podzielić "\\."jako „”. jest specjalny dla wyrażenia regularnego.
— Kompas

1

utwórz nowy plik ze ścieżką do obrazu

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

Na org.apache.commons.io.FilenameUtils w wersji 2.4 można znaleźć następującą odpowiedź

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

Zrobiłbym tak:

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

Od początku do końca, aż do znaku „.” następnie wywołaj podciąg.

Edycja: Może nie golf, ale jest skuteczny :)


7
W zasadzie to i tak robi lastIndexOf; po co wymyślać koło na nowo?
— Michael Myers

Dla zabawy i trochę opisowego. tylko to. (a zapomniałem o lastIndexOf kiedy to pisałem)
— fmsf

0

Należy pamiętać o scenariuszach, w których nie ma rozszerzenia pliku lub istnieje więcej niż jedno rozszerzenie pliku

przykład Nazwa pliku: plik | plik.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();
}

Spowoduje to wyświetlenie przykładu zarówno dla img, jak i 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;
}

Spowoduje to przekształcenie „a.jpg.jpg” na „a” zamiast (poprawnego) „a.jpg”. Jaki jest cel file.length() > 0czeku?
— Klaus Gütter

Głównym pytaniem było „jak usunąć rozszerzenie?”, Więc tak, przekształcenie „a.txt.zip” na „a” i „.htaccess” w pustkę. Ta funkcja działa z ciągami znaków, więc nazwy plików nie mogą być zerowe, ale nadal mogą mieć długość 0, szybsze sprawdzenie, czy warto przed analizowaniem symboli. Pozdrowienia.
— Alexey,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.