Java: dividindo o nome do arquivo em uma base e extensão

Existe uma maneira melhor de obter o nome de arquivo e a extensão do arquivo do 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); 

Eu sei que outros mencionaram String.split , mas aqui está uma variante que só produz dois tokens (a base e a extensão):

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

Por exemplo:

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

Rendimentos:

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

A expressão regular informa ao Java para dividir em qualquer período que seja seguido por qualquer número de não-períodos, seguido pelo final da input. Há apenas um período que corresponde a essa definição (ou seja, o último período).

Tecnicamente falando de forma regular, essa técnica é chamada de lookahead positivo de largura zero .


BTW, se você quiser dividir um caminho e obter o nome completo do arquivo incluindo, mas não se limitando à extensão do ponto, usando um caminho com barras,

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

Por exemplo:

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

Pergunta antiga, mas eu costumo usar essa solução:

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

O Java 7 em diante possui uma interface chamada Path para cuidar dessas coisas de maneira portátil :

 Path p = FileSystems.getDefault().getPath(nam); p.getParent(); 

Se você gosta das APIs mais antigas, use a class File .

 File f = new File(nam); f.getParent(); 

Extensões de arquivos são um conceito quebrado

E não existe uma function confiável para isso. Considere por exemplo este nome de arquivo:

 archive.tar.gz 

Qual é a extensão? Usuários do DOS teriam preferido o nome archive.tgz . Às vezes, você vê aplicativos estúpidos do Windows que primeiro descompactam o arquivo (gerando um arquivo .tar ), então você precisa abri-lo novamente para ver o conteúdo do arquivo.

Nesse caso, uma noção mais razoável de extensão de arquivo teria sido .tar.gz . Existem também extensões ” .tar.bz2 , .tar.xz , .tar.lz e .tar.lzma ” em uso. Mas como você decidiria se dividir no último ponto ou no penúltimo ponto?

Use tipos mime em vez disso.

A function Java 7 Files.probeContentType provavelmente será muito mais confiável para detectar tipos de arquivos do que confiar na extensão de arquivo. Praticamente todo o mundo Unix / Linux, assim como o seu Webbrowser e Smartphone, já o fazem dessa maneira.

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

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

Java tem funções internas para obter o nome de base e o nome de diretório para um determinado caminho de arquivo, mas os nomes de function não são tão auto-aparentes.

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

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

tal class de utilidade:

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

O que há de errado com seu código? Embrulhado em um método de utilidade puro está bem.

O que é mais importante é o que usar como separador – o primeiro ou último ponto. O primeiro é ruim para nomes de arquivos como “setup-2.5.1.exe”, o último é ruim para nomes de arquivos com várias extensões como “mybundle.tar.gz”.

Você também pode usar o java Regular Expression. String.split () também usa a expressão internamente. Consulte http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html

Talvez você possa usar String # split

Para responder seu comentário:

Não tenho certeza se pode haver mais de um. em um nome de arquivo, mas seja qual for, mesmo que haja mais pontos, você pode usar a divisão. Considere, por exemplo, que:

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

Isso retornará uma matriz contendo:

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

Então você saberá que o último índice na matriz é a extensão e todos os outros são a base.