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
o mój Boże
źródło
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

skaffman
źródło
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('.'))
Svitlana Maksymchuk
źródło
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ć.

coobird
źródło
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;
Edward Falk
źródło
16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));
Jherico
źródło
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.

Huxi
źródło
7

Użyj metody w com.google.common.io.Filesklasie, jeśli Twój projekt jest już zależny od podstawowej biblioteki Google. Metoda, której potrzebujesz, to getNameWithoutExtension.

Toby
źródło
Dlaczego ktoś jest przeciwko mojej odpowiedzi?
Toby,
Zwróć uwagę, że zwraca to tylko nazwę podstawową, więc ścieżka również jest usuwana: google.github.io/guava/releases/19.0/api/docs/com/google/common/ ...
thSoft
6

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

public String getWithoutExtension(String fileFullPath){
    return fileFullPath.substring(0, fileFullPath.lastIndexOf('.'));
}
Shantonu
źródło
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"
mxro
źródło
5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();
Alexander
źródło
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.

Steven Spungin
źródło
1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");
Mahdak
źródło
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 "";
        }
    }
Pravin Bhosale
źródło
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 = '\\';
Ktoś gdzieś
źródło
1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }
supernowa
źródło
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 :)

fmsf
źródło
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;
}
Choesang
źródło
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

urs86ro
źródło
0
public static String removeExtension(String file) {
    if(file != null && file.length() > 0) {
        while(file.contains(".")) {
            file = file.substring(0, file.lastIndexOf('.'));
        }
    }
    return file;
}
Alexey
źródło
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,