¿Cómo obtener el nombre de archivo sin la extensión en Java?

Respuestas:

429

Si usted, como yo, prefiere usar algún código de biblioteca donde probablemente hayan pensado en todos los casos especiales, como lo que sucede si pasa puntos o nulos en la ruta pero no en el nombre del archivo, puede usar lo siguiente:

import org.apache.commons.io.FilenameUtils;
String fileNameWithOutExt = FilenameUtils.removeExtension(fileNameWithExt);
Ulf Lindback
fuente
61
también puede usar FilenameUtils.getBasename para ir directamente de una cadena de ruta a un nombre de archivo sin extensión.
Ian Durkan
2
Lo más fácil es, por supuesto, ejecutar maven :-) De lo contrario, ver: commons.apache.org/io
Ulf Lindback
8
Para aquellos que prefieren la guayaba, también puede hacer esto . (En estos días, personalmente no me siento muy bien al agregar dependencias de Apache Commons, aunque históricamente esas bibliotecas han sido muy útiles.)
Jonik
3
Si bien Guava y Commons-IO pueden ofrecer un poco más, se sorprenderá de cuántos métodos de conveniencia ya están incluidos en JDK 7 con java.nio.file.Filesy Path, como resolver directorios base, copiar / mover archivos en una línea, obtener solo el nombre del archivo etc.
Don Cheadle
3
@Lan Durkan actualmente FilenameUtils.getBaseName con N mayúscula
Lento Harry
153

La forma más fácil es usar una expresión regular.

fileNameWithOutExt = "test.xml".replaceFirst("[.][^.]+$", "");

La expresión anterior eliminará el último punto seguido de uno o más caracteres. Aquí hay una prueba de unidad básica.

public void testRegex() {
    assertEquals("test", "test.xml".replaceFirst("[.][^.]+$", ""));
    assertEquals("test.2", "test.2.xml".replaceFirst("[.][^.]+$", ""));
}
brianegge
fuente
11
Regex no es tan fácil de usar como la solución de biblioteca anterior. Funciona, pero mirar el código (sin tener que interpretar el REGEX) no es obvio lo que hace.
Gustavo Litovsky
55
@GustavoLitovsky Android no viene incluido org.apache.commons. Que yo sepa, esta es la única forma de hacerlo en Android.
Liam George Betsworth
1
/ * la siguiente expresión regular también elimina la ruta * / "/the/path/name.extension".replaceAll(".*[\\\\/font>|\\.[^\\.font>*$", "") ;
daggett
1
Agregaría barras a la segunda clase de caracteres para asegurarme de que no te tropieces con un camino como "/foo/bar.x/baz"
chrisinmtown
53

Vea el siguiente programa de prueba:

public class javatemp {
    static String stripExtension (String str) {
        // Handle null case specially.

        if (str == null) return null;

        // Get position of last '.'.

        int pos = str.lastIndexOf(".");

        // If there wasn't any '.' just return the string as is.

        if (pos == -1) return str;

        // Otherwise return the string, up to the dot.

        return str.substring(0, pos);
    }

    public static void main(String[] args) {
        System.out.println ("test.xml   -> " + stripExtension ("test.xml"));
        System.out.println ("test.2.xml -> " + stripExtension ("test.2.xml"));
        System.out.println ("test       -> " + stripExtension ("test"));
        System.out.println ("test.      -> " + stripExtension ("test."));
    }
}

que salidas:

test.xml   -> test
test.2.xml -> test.2
test       -> test
test.      -> test
paxdiablo
fuente
¿Cuál es la extensión de foo.tar.gz? Puedo ver por qué .tar.gzsería lo que querrías.
tchrist
55
@tchrist, foo.tar.gzes una versión comprimida de, foo.tarpor lo que también podría argumentar que esa gzera la extensión. Todo se reduce a cómo define la extensión.
paxdiablo
2
¿Qué hacer con los archivos .gitignore?
michael nesterenko
como sabes, el nombre de la clase en java nunca debe comenzar con letras minúsculas.
AnujKu
77
Si eso fuera una regla, el lenguaje lo haría cumplir. Como no es así, es una guía, aunque se sugiere encarecidamente. En cualquier caso, eso es totalmente irrelevante para la pregunta y la respuesta.
paxdiablo
47

Aquí está el orden de la lista consolidada por mi preferencia.

Usando apache commons

import org.apache.commons.io.FilenameUtils;

String fileNameWithoutExt = FilenameUtils.getBaseName(fileName);

                           OR

String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);

Usando Google Guava (si ya lo estás usando)

import com.google.common.io.Files;
String fileNameWithOutExt = Files.getNameWithoutExtension(fileName);

O usando Core Java

1)

String fileName = file.getName();
int pos = fileName.lastIndexOf(".");
if (pos > 0 && pos < (fileName.length() - 1)) { // If '.' is not the first or last character.
    fileName = fileName.substring(0, pos);
}

2)

if (fileName.indexOf(".") > 0) {
   return fileName.substring(0, fileName.lastIndexOf("."));
} else {
   return fileName;
}

3)

private static final Pattern ext = Pattern.compile("(?<=.)\\.[^.]+$");

public static String getFileNameWithoutExtension(File file) {
    return ext.matcher(file.getName()).replaceAll("");
}

API de Liferay

import com.liferay.portal.kernel.util.FileUtil; 
String fileName = FileUtil.stripExtension(file.getName());
Om
fuente
42

Si su proyecto usa guayaba (14.0 o más reciente), puede ir con Files.getNameWithoutExtension().

(Esencialmente lo mismo que FilenameUtils.removeExtension()de Apache Commons IO, como sugiere la respuesta más votada . Solo quería señalar que Guava hace esto también. Personalmente no quería agregar dependencia a Commons, lo cual creo que es un poco una reliquia) solo por esto)

Jonik
fuente
2
en realidad es más comoFilenameUtils.getBaseName()
Angelo.Hannes
en realidad, la guayaba es una lib tan inestable que evito usarla siempre que puedo. prefiero una reliquia estable que los experimentos de googel
Slava
8

A continuación se muestra una referencia de https://android.googlesource.com/platform/tools/tradefederation/+/master/src/com/android/tradefed/util/FileUtil.java

/**
 * Gets the base name, without extension, of given file name.
 * <p/>
 * e.g. getBaseName("file.txt") will return "file"
 *
 * @param fileName
 * @return the base name
 */
public static String getBaseName(String fileName) {
    int index = fileName.lastIndexOf('.');
    if (index == -1) {
        return fileName;
    } else {
        return fileName.substring(0, index);
    }
}
David Cheung
fuente
1
Buena información, pero usuarios, estén atentos a casos como ".htaccess", donde este método devolverá "".
Markus Schulte
6

Si no desea importar los apache.commons completos, he extraído la misma funcionalidad:

public class StringUtils {
    public static String getBaseName(String filename) {
        return removeExtension(getName(filename));
    }

    public static int indexOfLastSeparator(String filename) {
        if(filename == null) {
            return -1;
        } else {
            int lastUnixPos = filename.lastIndexOf(47);
            int lastWindowsPos = filename.lastIndexOf(92);
            return Math.max(lastUnixPos, lastWindowsPos);
        }
    }

    public static String getName(String filename) {
        if(filename == null) {
            return null;
        } else {
            int index = indexOfLastSeparator(filename);
            return filename.substring(index + 1);
        }
    }

    public static String removeExtension(String filename) {
        if(filename == null) {
            return null;
        } else {
            int index = indexOfExtension(filename);
            return index == -1?filename:filename.substring(0, index);
        }
    }

    public static int indexOfExtension(String filename) {
        if(filename == null) {
            return -1;
        } else {
            int extensionPos = filename.lastIndexOf(46);
            int lastSeparator = indexOfLastSeparator(filename);
            return lastSeparator > extensionPos?-1:extensionPos;
        }
    }
}
Hamzeh Soboh
fuente
4

Si bien creo firmemente en la reutilización de bibliotecas, el org.apache.commons.io JAR es 174 KB, que es notablemente grande para una aplicación móvil.

Si descarga el código fuente y echa un vistazo a su clase FilenameUtils, puede ver que hay muchas utilidades adicionales, y hace frente a las rutas de Windows y Unix, lo cual es encantador.

Sin embargo, si solo desea un par de métodos de utilidad estática para usar con rutas de estilo Unix (con un separador "/"), puede encontrar útil el siguiente código.

El removeExtensionmétodo conserva el resto de la ruta junto con el nombre del archivo. También hay un similar getExtension.

/**
 * Remove the file extension from a filename, that may include a path.
 * 
 * e.g. /path/to/myfile.jpg -> /path/to/myfile 
 */
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);
    }
}

/**
 * Return the file extension from a filename, including the "."
 * 
 * e.g. /path/to/myfile.jpg -> .jpg
 */
public static String getExtension(String filename) {
    if (filename == null) {
        return null;
    }

    int index = indexOfExtension(filename);

    if (index == -1) {
        return filename;
    } else {
        return filename.substring(index);
    }
}

private static final char EXTENSION_SEPARATOR = '.';
private static final char DIRECTORY_SEPARATOR = '/';

public static int indexOfExtension(String filename) {

    if (filename == null) {
        return -1;
    }

    // Check that no directory separator appears after the 
    // EXTENSION_SEPARATOR
    int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);

    int lastDirSeparator = filename.lastIndexOf(DIRECTORY_SEPARATOR);

    if (lastDirSeparator > extensionPos) {
        LogIt.w(FileSystemUtil.class, "A directory separator appears after the file extension, assuming there is no file extension");
        return -1;
    }

    return extensionPos;
}
Dan J
fuente
1
public static String getFileExtension(String fileName) {
        if (TextUtils.isEmpty(fileName) || !fileName.contains(".") || fileName.endsWith(".")) return null;
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    public static String getBaseFileName(String fileName) {
        if (TextUtils.isEmpty(fileName) || !fileName.contains(".") || fileName.endsWith(".")) return null;
        return fileName.substring(0,fileName.lastIndexOf("."));
    }
Gil SH
fuente
1

La forma más simple de obtener el nombre de la ruta relativa o la ruta completa es usar

import org.apache.commons.io.FilenameUtils; FilenameUtils.getBaseName(definitionFilePath)

Chetan Nehete
fuente
0

Puedes dividirlo por "." y en el índice 0 está el nombre del archivo y en 1 es la extensión, pero me inclinaría por la mejor solución con FileNameUtils de apache.commons-io como se mencionó en el primer artículo. No es necesario eliminarlo, pero es suficiente:

String fileName = FilenameUtils.getBaseName("test.xml");

Peter S.
fuente
0

Uso FilenameUtils.removeExtensionde Apache Commons IO

Ejemplo:

Puede proporcionar el nombre completo de la ruta o solo el nombre del archivo .

String myString1 = FilenameUtils.removeExtension("helloworld.exe"); // returns "helloworld"
String myString2 = FilenameUtils.removeExtension("/home/abc/yey.xls"); // returns "yey"

Espero que esto ayude ..

Dulith De Costa
fuente
Eso ya está en la respuesta aceptada, ¿cuál es el punto de esta publicación?
Tom
0

La forma fluida:

public static String fileNameWithOutExt (String fileName) {
    return Optional.of(fileName.lastIndexOf(".")).filter(i-> i >= 0)
            .map(i-> fileName.substring(0, i)).orElse(fileName);
}
Nolle
fuente
0

Manteniéndolo simple, use el método String.replaceAll () de Java de la siguiente manera:

String fileNameWithExt = "test.xml";
String fileNameWithoutExt
   = fileNameWithExt.replaceAll( "^.*?(([^/\\\\\\.]+))\\.[^\\.]+$", "$1" );

Esto también funciona cuando fileNameWithExt incluye la ruta completa.

gwc
fuente
0

Puede usar la función de división de Java para dividir el nombre de archivo de la extensión, si está seguro de que solo hay un punto en el nombre de archivo para la extensión.

File filename = new File('test.txt'); File.getName().split("[.]");

así split[0]que devolverá "test" y split [1] devolverá "txt"

Danés Ahmed
fuente
-3

Prueba el siguiente código. Uso de funciones básicas de Java básicas. Se ocupa de Strings con extensión, y sin extensión (sin el '.'carácter). El caso de múltiples '.'también está cubierto.

String str = "filename.xml";
if (!str.contains(".")) 
    System.out.println("File Name=" + str); 
else {
    str = str.substring(0, str.lastIndexOf("."));
    // Because extension is always after the last '.'
    System.out.println("File Name=" + str);
}

Puede adaptarlo para trabajar con nullcadenas.

Sksoni
fuente
1
Es una práctica bastante mala implementar este tipo de funcionalidad usted mismo. A primera vista, la tarea parece ser extremadamente obvia , pero en la práctica se enfrentará a muchas situaciones excepcionales (como no hay .un nombre de archivo, o el archivo es una copia de seguridad y tiene un nombre como document.docx.backup, etc.). Es mucho más confiable usar una biblioteca externa que se ocupa de todas estas situaciones excepcionales para usted.
ivstas
1
Por otro lado, agregar muchas bibliotecas a su proyecto lo hará más grande. Entonces, cosas simples como esta podrían hacerse usted mismo.
Nicolas Tyler
1
De ninguna manera deberías hacerlo tú mismo. Esto es difícil: archivos sin extensión pero. en ruta, rutas ftp, ventanas y barras unix, enlaces simbólicos, etc. Sin duda, fallará y al tratar de ganar un poco de memoria, agregará mucha inestabilidad. Como mínimo, copie las fuentes del código establecido si las licencias lo permiten.
Jonathan Nappee
Este código se parece al de Amit Mishra, excepto por ese intimidante 'if (! Str.contains ("."))'
Broken_Window
fallaría en el siguiente caso "/someFolder/some.other.folder/someFileWithoutExtention". Lo primero que me vino a la mente después de 2 segundos ... estoy seguro de que podría encontrar muchos otros ejemplos.
Newtopian