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.