Comment découper une extension de fichier d'une chaîne en Java?

177

Quel est le moyen le plus efficace de couper le suffixe en Java, comme ceci:

title part1.txt
title part2.html
=>
title part1
title part2
OMG
la source
2
code efficace sage, est ce que vous voulez dire que je l' espère, pas sage CPU
mkoryak
3
Il ne demandait pas comment faire, il demandait quelle était la manière la plus efficace. Je suis venu ici à la recherche de la même chose.
Edward Falk

Réponses:

285

C'est le genre de code que nous ne devrions pas faire nous-mêmes. Utilisez des bibliothèques pour les choses banales, gardez votre cerveau pour les choses difficiles.

Dans ce cas, je recommande d'utiliser FilenameUtils.removeExtension () d' Apache Commons IO

skaffman
la source
7
Absolument bang dessus.
Joshua Pinter
6
Pour 95% des projets, cela devrait être la réponse acceptée. La réécriture de code comme celui-ci est à l'origine de nombreux maux de tête!
Carsten Hoffmann
1
Ajoutez simplement la ligne suivante dans gradle pour ajouter la dépendance: - compilez 'commons-io: commons-io: 2.6'
Deepak Sharma
exemple s'il vous plaît.
john ktejik
8
Si vous avez déjà des E / S Apache Commons dans votre projet, c'est vrai. Mais si tout ce dont vous avez besoin, vous ajoutez (au moins) 2,5 Mo de poids mort à votre projet pour quelque chose qui peut être facilement réalisé avec une seule ligne.
foo le
229
str.substring(0, str.lastIndexOf('.'))
Svitlana Maksymchuk
la source
8
Cela doit être affecté à une nouvelle variable car str n'est pas modifié.
Nathan Feger
51
Manipulez avec précaution: cela vous lancera une exception si le nom du fichier n'a pas de suffixe.
Andreas Dolk
24
qu'en est-il de 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 est une autre dépendance, et pas toujours disponible
ocramot
88

Comme l'utilisation de String.substringet String.lastIndexdans une seule ligne est une bonne chose, il y a quelques problèmes en termes de capacité à gérer certains chemins de fichiers.

Prenons par exemple le chemin suivant:

a.b/c

L'utilisation du one-liner entraînera:

a

C'est incorrect.

Le résultat aurait dû être c, mais comme le fichier n'avait pas d'extension, mais que le chemin avait un répertoire avec un .dans le nom, la méthode one-liner a été trompée en donnant une partie du chemin comme nom de fichier, ce qui n'est pas correct.

Besoin de chèques

Inspiré par la réponse de skaffman , j'ai jeté un coup d'œil à la FilenameUtils.removeExtensionméthode de l' Apache Commons IO .

Afin de recréer son comportement, j'ai écrit quelques tests que la nouvelle méthode devrait remplir, qui sont les suivants:

Nom de fichier du chemin
-------------- --------
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

(Et c'est tout ce que j'ai vérifié - il y a probablement d'autres contrôles qui devraient être en place que j'ai négligés.)

La mise en oeuvre

Voici mon implémentation pour la removeExtensionméthode:

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

L'exécution de cette removeExtensionméthode avec les tests ci-dessus donne les résultats énumérés ci-dessus.

La méthode a été testée avec le code suivant. Comme cela a été exécuté sous Windows, le séparateur de chemin est un \qui doit être échappé avec un \lorsqu'il est utilisé dans le cadre d'un Stringlittéral.

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

Les résultats ont été:

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

Les résultats sont les résultats souhaités décrits dans le test que la méthode doit remplir.

coobird
la source
4
Très bonne réponse. Y a-t-il une raison particulière pour laquelle vous utilisez System.getProperty("file.separator")et pas seulement File.separator?
halirutan le
2
Un mot d'avertissement: cette solution supprime également le chemin précédent, pas seulement l'extension, contrairement à la méthode Apache Commons IO.
DHa
3
Il semble que cela échouera pour le/path/to/.htaccess
Kuzeko
17

BTW, dans mon cas, lorsque je voulais une solution rapide pour supprimer une extension spécifique, c'est à peu près ce que j'ai fait:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;
Edward Falk
la source
16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));
Jherico
la source
4
Non, il peut y en avoir plus d'un "."; vous voulez lastIndexOf ('.')
Adam Jaskiewicz
-1 pour ne pas utiliser la méthode que je pensais que vous utilisiez. C'est maintenant un total de +0 de ma part. Changez-le vite! ;)
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);
}

Est-ce une question piège? : p

Je ne peux pas penser à un guichet automatique plus rapide.

Huxi
la source
7

Utilisez une méthode en com.google.common.io.Filesclasse si votre projet dépend déjà de la bibliothèque principale de Google. La méthode dont vous avez besoin est getNameWithoutExtension.

Toby
la source
Pourquoi quelqu'un est contre ma réponse ??
Toby
Notez que cela renvoie uniquement le nom de base, donc le chemin est également supprimé: google.github.io/guava/releases/19.0/api/docs/com/google/common/…
thSoft
6

vous pouvez essayer cette fonction, très basique

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

J'ai trouvé la réponse de coolbird particulièrement utile.

Mais j'ai changé les dernières déclarations de résultat en:

if (extensionIndex == -1)
  return s;

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

car je voulais que le nom complet du chemin soit renvoyé.

Ainsi "C: \ Users \ mroh004.COM \ Documents \ Test \ Test.xml" devient 
   "C: \ Users \ mroh004.COM \ Documents \ Test \ Test" et non
   "Tester"
mxro
la source
5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();
Alexandre
la source
3
En face de ce qui a été demandé et il n'est pas nécessaire de passer la longueur, utilisez simplement une sous
4

Utilisez une expression régulière. Celui-ci remplace le dernier point, et tout ce qui suit.

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

Vous pouvez également créer un objet Pattern si vous souhaitez précompiler le regex.

Steven Spungin
la source
1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");
Mahdak
la source
Besoin de diviser "\\."en "." est spécial pour regex.
Compass
1

créer un nouveau fichier avec le chemin de l'image de chaîne

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
la source
1

org.apache.commons.io.FilenameUtils version 2.4 donne la réponse suivante

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 = '\\';
Quelqu'un quelque part
la source
1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }
supernova
la source
0

Je voudrais faire comme ceci:

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

De la fin jusqu'au '.' puis appelez substring.

Edit: Ce n'est peut-être pas un golf mais c'est efficace :)

fmsf
la source
7
C'est essentiellement ce que fait lastIndexOf; pourquoi réinventer la roue?
Michael Myers
Pour le plaisir et pour être un peu descriptif. juste ça. (et j'ai oublié lastIndexOf quand j'écrivais ceci)
fmsf
0

En gardant à l'esprit les scénarios où il n'y a pas d'extension de fichier ou il y a plus d'une extension de fichier

exemple Nom de fichier: fichier | 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
la source
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();
}

Cela affichera un exemple pour img et imgLink

urs86ro
la source
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
la source
Cela transformera "a.jpg.jpg" en "a" au lieu du (correct) "a.jpg". Dans quel but sert le file.length() > 0chèque?
Klaus Gütter
La question principale était "comment supprimer l'extension?", Donc oui, sa transformation "a.txt.zip" en "a" et ".htaccess" en vide. Cette fonction fonctionne avec les chaînes, donc les noms de fichiers peuvent ne pas être nuls mais peuvent toujours avoir une longueur de 0, vérifiez plus rapidement si cela en vaut la peine avant d'analyser les symboles. Cordialement.
Alexey