Wie schneide ich eine Dateierweiterung aus einem String in Java?

176

Was ist der effizienteste Weg, um das Suffix in Java wie folgt zu kürzen:

title part1.txt
title part2.html
=>
title part1
title part2
Oh mein Gott
quelle
2
Effizienter Code, ist das, was Sie meinen, ich hoffe, nicht CPU-weise
mkoryak
3
Er fragte nicht, wie es geht, er fragte, was der effizienteste Weg sei. Ich bin hierher gekommen, um dasselbe zu suchen.
Edward Falk

Antworten:

284

Dies ist die Art von Code, die wir nicht selbst machen sollten. Verwenden Sie Bibliotheken für das Alltägliche, retten Sie Ihr Gehirn für das Harte.

In diesem Fall empfehle ich die Verwendung von FilenameUtils.removeExtension () von Apache Commons IO

Skaffman
quelle
7
Absolut knallhart.
Joshua Pinter
6
Für 95% der Projekte sollte dies die akzeptierte Antwort sein. Das Umschreiben von Code wie diesem ist die Hauptursache für viele Kopfschmerzen!
Carsten Hoffmann
1
Fügen Sie einfach die folgende Zeile in Gradle hinzu, um die Abhängigkeit hinzuzufügen: - Kompilieren Sie 'commons-io: commons-io: 2.6'
Deepak Sharma
Beispiel bitte.
John Ktejik
8
Wenn Sie Apache Commons I / O bereits in Ihrem Projekt haben, ist das richtig. Wenn dies jedoch alles ist, was Sie dafür benötigen, fügen Sie Ihrem Projekt (mindestens) 2,5 MB Eigengewicht hinzu, um etwas zu erreichen, das problemlos mit einer einzigen Zeile erledigt werden kann.
foo
226
str.substring(0, str.lastIndexOf('.'))
Svitlana Maksymchuk
quelle
8
Dies sollte einer neuen Variablen zugewiesen werden, da str nicht geändert wird.
Nathan Feger
51
Gehen Sie vorsichtig vor: Es wird eine Ausnahme auf Sie geworfen, wenn der Dateiname kein Suffix hat.
Andreas Dolk
24
Was ist mit 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 ist eine weitere Abhängigkeit und nicht immer verfügbar
Ocramot
88

Da die Verwendung von String.substringund String.lastIndexin einem Einzeiler gut ist, gibt es einige Probleme hinsichtlich der Fähigkeit, mit bestimmten Dateipfaden umzugehen.

Nehmen Sie zum Beispiel den folgenden Weg:

a.b/c

Die Verwendung des Einzeilers führt zu:

a

Das ist falsch

Das Ergebnis hätte sein sollen c, aber da der Datei eine Erweiterung fehlte, der Pfad jedoch ein Verzeichnis mit einem .im Namen hatte, wurde die Einzeiler-Methode dazu verleitet, einen Teil des Pfads als Dateinamen anzugeben, was nicht korrekt ist.

Notwendigkeit von Schecks

Inspiriert von Skaffmans Antwort , habe ich mir die FilenameUtils.removeExtensionMethode des Apache Commons IO angesehen .

Um sein Verhalten wiederherzustellen, habe ich einige Tests geschrieben, die die neue Methode erfüllen sollte:

Pfad Dateiname
-------------- --------
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

(Und das ist alles, worauf ich überprüft habe - es gibt wahrscheinlich andere Überprüfungen, die vorhanden sein sollten, die ich übersehen habe.)

Die Umsetzung

Das Folgende ist meine Implementierung für die removeExtensionMethode:

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

Wenn Sie diese removeExtensionMethode mit den oben genannten Tests ausführen, erhalten Sie die oben aufgeführten Ergebnisse.

Die Methode wurde mit dem folgenden Code getestet. Da dies unter Windows ausgeführt wurde, ist das Pfadtrennzeichen ein, \das \bei Verwendung als Teil eines StringLiteral mit einem Escapezeichen versehen werden muss.

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

Die Ergebnisse waren:

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

Die Ergebnisse sind die gewünschten Ergebnisse, die in dem Test aufgeführt sind, den die Methode erfüllen sollte.

Coobird
quelle
4
Gute Antwort. Gibt es einen bestimmten Grund, warum Sie verwenden System.getProperty("file.separator")und nicht nur File.separator?
Halirutan
2
Ein Wort der Warnung: Diese Lösung entfernt im Gegensatz zur Apache Commons IO-Methode auch den vorhergehenden Pfad und nicht nur die Erweiterung.
DHa
3
Es scheint, dass dies für die/path/to/.htaccess
Kuzeko
17

Übrigens, in meinem Fall, als ich eine schnelle Lösung zum Entfernen einer bestimmten Erweiterung wollte, habe ich ungefähr Folgendes getan:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;
Edward Falk
quelle
16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));
Jherico
quelle
4
Nein, es könnte mehr als ein '.' Geben. du willst lastIndexOf ('.')
Adam Jaskiewicz
-1 für die Nichtanwendung der Methode, von der ich dachte, dass Sie sie verwenden. Das sind jetzt insgesamt +0 von mir. Ändere es schnell! ;)
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);
}

Ist das eine Trickfrage? : p

Ich kann mir keinen schnelleren Weg vorstellen.

Huxi
quelle
7

Verwenden Sie eine Methode im com.google.common.io.FilesUnterricht, wenn Ihr Projekt bereits von der Google-Kernbibliothek abhängig ist. Die Methode, die Sie benötigen, ist getNameWithoutExtension.

Toby
quelle
Warum ist jemand gegen meine Antwort?
Toby
Beachten Sie, dass dies nur den Basisnamen
zurückgibt
6

Sie können diese Funktion ausprobieren, sehr einfach

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

Ich habe die Antwort von coolbird gefunden besonders nützlich.

Aber ich habe die letzten Ergebnisaussagen geändert in:

if (extensionIndex == -1)
  return s;

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

da ich wollte, dass der vollständige Pfadname zurückgegeben wird.

So wird "C: \ Users \ mroh004.COM \ Documents \ Test \ Test.xml" 
   "C: \ Users \ mroh004.COM \ Documents \ Test \ Test" und nicht
   "Prüfung"
mxro
quelle
5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();
Alexander
quelle
3
Im Gegensatz zu dem, was gefragt wurde und es nicht notwendig ist, die Länge zu übergeben, verwenden Sie einfach einen arg-Teilstring
4

Verwenden Sie einen regulären Ausdruck. Dieser ersetzt den letzten Punkt und alles danach.

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

Sie können auch ein Musterobjekt erstellen, wenn Sie den regulären Ausdruck vorkompilieren möchten.

Steven Spungin
quelle
1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");
Mahdak
quelle
Müssen "\\."als "." ist speziell für Regex.
Kompass
1

Erstellen Sie eine neue Datei mit dem Pfad des Zeichenfolgenbilds

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
quelle
1

org.apache.commons.io.FilenameUtils Version 2.4 gibt die folgende Antwort

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 = '\\';
Irgendwer irgendwo
quelle
1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }
Supernova
quelle
0

Das würde mir gefallen:

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

Vom Ende bis zum '.' Rufen Sie dann Teilzeichenfolge auf.

Edit: Könnte kein Golf sein, aber es ist effektiv :)

fmsf
quelle
7
Genau das macht lastIndexOf sowieso. Warum das Rad neu erfinden?
Michael Myers
Zum Spaß und um ein bisschen beschreibend zu sein. nur das. (und ich habe lastIndexOf vergessen, als ich das schrieb)
fmsf
0

Beachten Sie die Szenarien, in denen es keine Dateierweiterung oder mehr als eine Dateierweiterung gibt

Beispiel Dateiname: Datei | 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;
}
Choesang
quelle
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();
}

Dies gibt ein Beispiel für img und imgLink aus

urs86ro
quelle
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
quelle
Dadurch wird "a.jpg.jpg" in "a" anstelle des (korrekten) "a.jpg" umgewandelt. Welchem ​​Zweck dient die file.length() > 0Prüfung?
Klaus Gütter
Die Hauptfrage war "Wie entferne ich die Erweiterung?", Also ja, die Transformation "a.txt.zip" in "a" und ".htaccess" in Leere. Diese Funktion funktioniert mit Strings, sodass Dateinamen nicht null, aber dennoch 0 lang sein können. Überprüfen Sie schneller, ob es sich lohnt, bevor Sie Symbole analysieren. Grüße.
Alexey