Java: dividir el nombre del archivo en una base y una extensión


83

¿Hay una mejor manera de obtener el nombre de base y la extensión del archivo que algo como

File f = ...
String name = f.getName();
int dot = name.lastIndexOf('.');
String base = (dot == -1) ? name : name.substring(0, dot);
String extension = (dot == -1) ? "" : name.substring(dot+1);

7
Eche un vistazo a commons-io FilenameUtils . Tiene los métodos getBaseName(..)y getExtension(..).
Bozho

Por solamente la extensión, consulte stackoverflow.com/questions/3571223/... .
Andy Thomas

Respuestas:


168

Sé que otros han mencionado String.split, pero aquí hay una variante que solo produce dos tokens (la base y la extensión):

String[] tokens = fileName.split("\\.(?=[^\\.]+$)");

Por ejemplo:

"test.cool.awesome.txt".split("\\.(?=[^\\.]+$)");

Rendimientos:

["test.cool.awesome", "txt"]

La expresión regular le dice a Java que se divida en cualquier período seguido por cualquier número de no períodos, seguido del final de la entrada. Solo hay un período que coincide con esta definición (a saber, el último período).

Técnicamente hablando con expresiones regulares, esta técnica se denomina anticipación positiva de ancho cero .


Por cierto, si desea dividir una ruta y obtener el nombre de archivo completo, incluida, entre otras, la extensión de punto, utilizando una ruta con barras diagonales,

    String[] tokens = dir.split(".+?/(?=[^/]+$)");

Por ejemplo:

    String dir = "/foo/bar/bam/boozled"; 
    String[] tokens = dir.split(".+?/(?=[^/]+$)");
    // [ "/foo/bar/bam/" "boozled" ] 

2
No tengo idea de por qué la gente tiene miedo a las dependencias ;-)
Bozho

3
@Bozho: Estoy de acuerdo en que las bibliotecas son mejores soluciones para este tipo de problemas. Permite que otras personas mantengan y piensen por ti (¡por eso voté tu respuesta!). Esto puede sonar trivial, pero hay una parte de mí que siempre duda cuando considero incluir una biblioteca Apache porque he sufrido el "infierno JAR" en el pasado con algunas de sus cosas (lo sé, es trivial).
Adam Paynter

4
@Bozho: Adam tiene toda la razón. Este problema no sería suficiente para justificarme asumir otra biblioteca, pero si ya estuviera usando commons-io por otras razones, entonces usaría Filenameutils.
Jason S

1
@Jason: Expresiones regulares: el regalo que sigue dando. :)
Adam Paynter

3
@Bozho - ¿Sarcasmo? La verdadera pregunta es por qué Java viene con montones interminables de clases redundantes que se acercan tanto a hacer que sea fácil hacer lo que realmente quieres hacer, pero frustrantemente nunca lo haces. No hay equivalente a Apache-Commons en Python porque Python simplemente tiene todas las cosas útiles que desea integradas. C # parece ser otro ejemplo de un lenguaje en el que puede concentrarse en su problema único en lugar de tener que averiguar cómo reinventar la rueda o ir a buscar la rueda que inventó otra persona.
ArtOfWarfare

84

Antigua pregunta pero suelo usar esta solución:

import org.apache.commons.io.FilenameUtils;

String fileName = "/abc/defg/file.txt";

String basename = FilenameUtils.getBaseName(fileName);
String extension = FilenameUtils.getExtension(fileName);
System.out.println(basename); // file
System.out.println(extension); // txt (NOT ".txt" !)

No funciona si se trabaja en Windows y la cadena "fileName" es "D: \ resources \ ftp_upload.csv". ¿Puedes ayudarme?
NIKHIL CHAURASIA

3
@NIKHILCHAURASIA necesitas escapar de las barras invertidas, duplicándolas. Como: "D: \\ recursos \\ ftp_upload.csv".
Ricket

8

Fuente: http://www.java2s.com/Code/Java/File-Input-Output/Getextensionpathandfilename.htm

tal clase de utilidad:

class Filename {
  private String fullPath;
  private char pathSeparator, extensionSeparator;

  public Filename(String str, char sep, char ext) {
    fullPath = str;
    pathSeparator = sep;
    extensionSeparator = ext;
  }

  public String extension() {
    int dot = fullPath.lastIndexOf(extensionSeparator);
    return fullPath.substring(dot + 1);
  }

  public String filename() { // gets filename without extension
    int dot = fullPath.lastIndexOf(extensionSeparator);
    int sep = fullPath.lastIndexOf(pathSeparator);
    return fullPath.substring(sep + 1, dot);
  }

  public String path() {
    int sep = fullPath.lastIndexOf(pathSeparator);
    return fullPath.substring(0, sep);
  }
}

uso:

public class FilenameDemo {
  public static void main(String[] args) {
    final String FPATH = "/home/mem/index.html";
    Filename myHomePage = new Filename(FPATH, '/', '.');
    System.out.println("Extension = " + myHomePage.extension());
    System.out.println("Filename = " + myHomePage.filename());
    System.out.println("Path = " + myHomePage.path());
  }
}

4
basename()sería un mejor nombre en lugar defilename()
nimcap

en caso de que no haya una extensión (por ejemplo, un nombre de archivo como "/ etc / hosts"), esto devolverá "hosts" como la extensión (en lugar de ""). Las clases de servicios públicos de nivel de biblioteca deben ocuparse de los casos de esquina.
Zach-M

6

http://docs.oracle.com/javase/6/docs/api/java/io/File.html#getName ()

De http://www.xinotes.org/notes/note/774/ :

Java tiene funciones integradas para obtener el nombre base y el nombre del directorio para una ruta de archivo determinada, pero los nombres de las funciones no son tan evidentes.

import java.io.File;

public class JavaFileDirNameBaseName {
    public static void main(String[] args) {
    File theFile = new File("../foo/bar/baz.txt");
    System.out.println("Dirname: " + theFile.getParent());
    System.out.println("Basename: " + theFile.getName());
    }
}

4
java.io.File.getName () devuelve el nombre con extensión.
Bram

2
Prefiero pensar que no existe tal cosa como "extensión" :-)

3
pero la pregunta es sobre cómo obtener la extensión ...
user85421

4

Las extensiones de archivo son un concepto roto

Y no existe una función confiable para ello. Considere, por ejemplo, este nombre de archivo:

archive.tar.gz

¿Qué es la extensión? Los usuarios de DOS hubieran preferido el nombre archive.tgz. A veces ves aplicaciones de Windows estúpidas que primero descomprimen el archivo (produciendo un .tararchivo), luego tienes que abrirlo nuevamente para ver el contenido del archivo.

En este caso, una noción más razonable de extensión de archivo habría sido .tar.gz. También hay .tar.bz2, .tar.xz, .tar.lzy .tar.lzma"Extensiones" Archivo en uso. Pero, ¿cómo decidiría si dividir en el último punto o en el penúltimo punto?

En su lugar, utilice tipos de mímica.

La función Files.probeContentType de Java 7 probablemente será mucho más confiable para detectar tipos de archivos que confiar en la extensión del archivo. Prácticamente todo el mundo Unix / Linux, así como su navegador web y su teléfono inteligente, ya lo hacen de esta manera.


6
¿Cómo responde esto a la pregunta? Ni Filetampoco Pathme dejo separar la extensión.
Andreas Abel

@ andreas.abel permítanme repetir esto: las extensiones de archivo son un concepto roto. No son fiables ni están bien definidos, excepto en los nombres de archivo de DOS 8 + 3 (considérelos .tar.gzfrente a .tgztodos los que son demasiado comunes en Unix). En su lugar, use tipos de mímica.
Ha SALIDO - Anony-Mousse

1
@ Anony-Mousse Bueno, estoy de acuerdo en principio, pero el 99,999% de todos los sistemas con los que interactúo usan un nombre de archivo, no un tipo mimo
Christian Sauer

¿Dónde está el problema de usar en Files.probeContentTypelugar de confiar en el nombre del archivo para tener la extensión correcta?
Ha QUIT - Anony-Mousse

3
Esto no responde a la pregunta. Tengo un caso de uso donde el nombre de archivo, una película, es un nombre + extensión. ¿Cómo extraería el nombre usando tipos mime?
Niek

1

¿Qué pasa con tu código? Envuelto en un método de utilidad ordenado, está bien.

Lo que es más importante es qué usar como separador: el primer o el último punto. El primero es malo para nombres de archivo como "setup-2.5.1.exe", el último es malo para nombres de archivo con múltiples extensiones como "mybundle.tar.gz".



-3

Quizás podrías usar String # split

Para responder a su comentario:

No estoy seguro de si puede haber más de uno. en un nombre de archivo, pero lo que sea, incluso si hay más puntos, puede usar la división. Considere, por ejemplo, que:

String input = "boo.and.foo";

String[] result = input.split(".");

Esto devolverá una matriz que contiene:

{ "boo", "and", "foo" }

Entonces sabrá que el último índice de la matriz es la extensión y todos los demás son la base.


bueno, sí, pero tendría que encontrar una expresión regular para la última .de una cadena
Jason S

1
Hmm, no estoy seguro, pero ¿no puedes usar "."? ¿O son más de 1 punto en un nombre de archivo?

2
Creo que esto funcionaría: fileName.split("\\.(?=[^\\.]+$)")
Adam Paynter

1
No puede asumir que solo hay un punto. Adam: gracias, lo intentaré.
Jason S

4
Esta respuesta es incorrecta. Debido a que el punto no tiene escape, devolverá una matriz vacía.
aled
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.