¿Cómo recorto una extensión de archivo de una cadena en Java?

176

¿Cuál es la forma más eficiente de recortar el sufijo en Java, así:

title part1.txt
title part2.html
=>
title part1
title part2
Dios mio
fuente
2
código eficiente, es lo que quieres decir, espero, no en cuanto a CPU
mkoryak
3
No preguntaba cómo hacerlo, preguntaba cuál era la forma más eficiente. Vine aquí buscando lo mismo.
Edward Falk

Respuestas:

285

Este es el tipo de código que no deberíamos estar haciendo nosotros mismos. Usa bibliotecas para las cosas mundanas, guarda tu cerebro para las cosas difíciles.

En este caso, recomiendo usar FilenameUtils.removeExtension () de Apache Commons IO

skaffman
fuente
77
Absolutamente golpear.
Joshua Pinter
66
Para el 95% de los proyectos, esta debería ser la respuesta aceptada. ¡Reescribir código como este es la causa de muchos dolores de cabeza!
Carsten Hoffmann
1
Simplemente agregue la siguiente línea en gradle para agregar la dependencia: - compile 'commons-io: commons-io: 2.6'
Deepak Sharma
ejemplo por favor.
John Ktejik
8
Si ya tiene Apache Commons I / O en su proyecto, está bien. Pero si esto es todo lo que necesita, está agregando (al menos) 2.5 MB de peso muerto a su proyecto para algo que se puede hacer fácilmente con una sola línea.
foo
226
str.substring(0, str.lastIndexOf('.'))
Svitlana Maksymchuk
fuente
8
Esto debe asignarse a una nueva variable ya que str no se modifica.
Nathan Feger
51
Maneje con cuidado: le lanzará una Excepción si el nombre del archivo no tiene sufijo.
Andreas Dolk
24
¿Qué pasa con archive.tar.bz2?
Antonio
20
if(str.contains(".")) str.substring(0, str.lastIndexOf('.'))
Nicolas Tyler
66
if (str! = nulo && str.contains (".")) str.substring (0, str.lastIndexOf ('.')). FilenameUtils es otra dependencia, y no siempre está disponible
ocramot
88

Como usar el String.substringy String.lastIndexen un one-liner es bueno, hay algunos problemas en términos de poder hacer frente a ciertas rutas de archivo.

Tome por ejemplo la siguiente ruta:

a.b/c

Usar el one-liner dará como resultado:

a

Eso es incorrecto

El resultado debería haber sido c, pero dado que el archivo carecía de una extensión, pero la ruta tenía un directorio con un .nombre, el método de una línea fue engañado para que diera parte de la ruta como nombre de archivo, lo cual no es correcto.

Necesidad de cheques

Inspirado por la respuesta de skaffman , eché un vistazo al FilenameUtils.removeExtensionmétodo de Apache Commons IO .

Para recrear su comportamiento, escribí algunas pruebas que el nuevo método debería cumplir, que son las siguientes:

Nombre de archivo de ruta
-------------- --------
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

(Y eso es todo lo que he verificado, probablemente haya otras comprobaciones que deberían estar en su lugar que he pasado por alto).

La implementación

La siguiente es mi implementación para el removeExtensionmétodo:

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

Ejecutar este removeExtensionmétodo con las pruebas anteriores produce los resultados enumerados anteriormente.

El método fue probado con el siguiente código. Como esto se ejecutó en Windows, el separador de ruta es un elemento \que debe escaparse con un \cuando se usa como parte de un Stringliteral.

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

Los resultados fueron:

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

Los resultados son los resultados deseados descritos en la prueba que el método debe cumplir.

Coobird
fuente
44
Gran respuesta. ¿Hay alguna razón particular por la que usas System.getProperty("file.separator")y no solo File.separator?
halirutan
2
Una advertencia: esta solución también elimina la ruta anterior, no solo la extensión, a diferencia del método Apache Commons IO.
DHa
3
Al parecer, esta fallará para el/path/to/.htaccess
Kuzeko
17

Por cierto, en mi caso, cuando quería una solución rápida para eliminar una extensión específica, esto es aproximadamente lo que hice:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;
Edward Falk
fuente
16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));
Jherico
fuente
44
No, puede haber más de un '.'; quieres lastIndexOf ('.')
Adam Jaskiewicz
-1 por no usar el método que pensé que estabas usando. Eso es ahora un total de +0 de mi parte. ¡Cámbialo rápido! ;)
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);
}

¿Es esta una pregunta con trampa? :pags

No puedo pensar en un cajero automático más rápido.

Huxi
fuente
7

Use un método en com.google.common.io.Filesclase si su proyecto ya depende de la biblioteca principal de Google. El método que necesitas es getNameWithoutExtension.

Toby
fuente
¿Por qué alguien está en contra de mi respuesta?
Toby
Tenga en cuenta que esto solo devuelve el nombre base, por lo que la ruta también se elimina: google.github.io/guava/releases/19.0/api/docs/com/google/common/…
thSoft
6

puedes probar esta función, muy básica

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

He encontrado la respuesta de coolbird particularmente útil.

Pero cambié las últimas declaraciones de resultados a:

if (extensionIndex == -1)
  return s;

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

ya que quería que se devolviera el nombre completo de la ruta.

Entonces "C: \ Users \ mroh004.COM \ Documents \ Test \ Test.xml" se convierte en 
   "C: \ Users \ mroh004.COM \ Documents \ Test \ Test" y no
   "Prueba"
mxro
fuente
5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();
Alejandro
fuente
3
Frente a lo que se pidió y no hay necesidad de pasar la longitud, solo use una subcadena arg
4

Usa una expresión regular. Este reemplaza el último punto, y todo lo que sigue.

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

También puede crear un objeto Patrón si desea precompilar la expresión regular.

Steven Spungin
fuente
1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");
Mahdak
fuente
Necesita dividirse "\\."como "." Es especial para expresiones regulares.
Brújula
1

crear un nuevo archivo con ruta de imagen de cadena

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

org.apache.commons.io.FilenameUtils versión 2.4 da la siguiente respuesta

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 = '\\';
Alguien en algún lugar
fuente
1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }
supernova
fuente
0

Me gustaría hacer esto:

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

Comenzando hasta el final hasta el '.' luego llame a la subcadena.

Editar: Puede que no sea un golf pero es efectivo :)

fmsf
fuente
77
Eso es básicamente lo que lastIndexOf hace de todos modos; ¿Por qué reinventar la rueda?
Michael Myers
Por diversión y para ser un poco descriptivo. solo eso. (y olvidé lastIndexOf cuando estaba escribiendo esto)
fmsf
0

Teniendo en cuenta los escenarios donde no hay extensión de archivo o hay más de una extensión de archivo

ejemplo Nombre de archivo: archivo | 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
fuente
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();
}

Esto generará ejemplos para img e imgLink

urs86ro
fuente
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
fuente
Esto transformará "a.jpg.jpg" en "a" en lugar del (correcto) "a.jpg". ¿Para qué sirve el file.length() > 0cheque?
Klaus Gütter
La pregunta principal era "¿cómo eliminar la extensión?", Así que sí, transforma "a.txt.zip" en "a" y ".htaccess" en el vacío. Esta función funciona con cadenas, por lo que los nombres de los archivos no pueden ser nulos pero aún pueden tener una longitud de 0, verifique más rápidamente si vale la pena antes de analizar los símbolos. Saludos.
Alexey