Como obter o nome do arquivo sem a extensão em Java?


Respostas:


429

Se você, como eu, preferir usar algum código de biblioteca em que eles provavelmente tenham pensado em todos os casos especiais, como o que acontece se você passar nulo ou pontos no caminho, mas não no nome do arquivo, use o seguinte:

import org.apache.commons.io.FilenameUtils;
String fileNameWithOutExt = FilenameUtils.removeExtension(fileNameWithExt);

61
você também pode usar FilenameUtils.getBasename para ir diretamente de uma cadeia de caminho para um nome de arquivo sem extensão.
Ian Durkan

2
O mais fácil, é claro, é executar o maven :-) Caso contrário, consulte: commons.apache.org/io
Ulf Lindback

8
Para quem prefere a goiaba, também pode fazer isso . (Esses dias eu pessoalmente não me sinto muito bem sobre a adição de Apache Commons dependências, embora historicamente essas bibliotecas têm sido muito úteis.)
Jonik

3
Embora o Guava e o Commons-IO possam oferecer um pouco mais, você ficará surpreso com quantos métodos de conveniência já estão incluídos no JDK 7 com java.nio.file.Filese Path- como resolver diretórios base, copiar / mover arquivos de uma linha, obter apenas o nome do arquivo etc.
Don Cheadle

3
@Lan Durkan atualmente FilenameUtils.getBaseName com capital N
Slow Harry

153

A maneira mais fácil é usar uma expressão regular.

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

A expressão acima removerá o último ponto seguido por um ou mais caracteres. Aqui está um teste de unidade básico.

public void testRegex() {
    assertEquals("test", "test.xml".replaceFirst("[.][^.]+$", ""));
    assertEquals("test.2", "test.2.xml".replaceFirst("[.][^.]+$", ""));
}

11
O Regex não é tão fácil de usar quanto a solução de biblioteca acima. Funciona, mas analisar o código (sem ter que interpretar o REGEX) não é óbvio o que ele faz.
Gustavo Litovsky

5
@GustavoLitovsky O Android não vem com o pacote org.apache.commons. Tanto quanto sei, esta é a única maneira de fazer isso no Android.
Liam George Betsworth

1
/ * o seguinte regex também remove o caminho * / "/the/path/name.extension".replaceAll(".*[\\\\/}|\\.[^\\.}*$", "") ;
21715 daggett

1
Gostaria de acrescentar barras para a segunda classe de caracteres para garantir que você não está desarmado por um caminho como "/foo/bar.x/baz"
chrisinmtown

53

Veja o seguinte programa de teste:

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

quais saídas:

test.xml   -> test
test.2.xml -> test.2
test       -> test
test.      -> test

Qual é a extensão de foo.tar.gz? Eu posso ver porque .tar.gzseria o que você gostaria.
tchrist

5
@tchrist, foo.tar.gzé uma versão compactada em gzip foo.tarpara que você também possa argumentar que essa gzera a extensão. Tudo se resume a como você define a extensão.
precisa

2
o que fazer com arquivos .gitignore?
michael Nesterenko

como você sabe o nome da classe em java nunca deve começar com letras minúsculas!
AnujKu

7
Se isso fosse uma regra, o idioma a aplicaria. Como não é, é uma diretriz, por mais fortemente que seja sugerida. De qualquer forma, isso é totalmente irrelevante para a pergunta e resposta.
precisa

47

Aqui está a ordem da lista consolidada de acordo com minha preferência.

Usando apache commons

import org.apache.commons.io.FilenameUtils;

String fileNameWithoutExt = FilenameUtils.getBaseName(fileName);

                           OR

String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);

Usando o Google Guava (se você já estiver usando)

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

Ou usando o 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 do Liferay

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

42

Se o seu projeto usa o Guava (14.0 ou mais recente), você pode prosseguir Files.getNameWithoutExtension().

(Essencialmente, o mesmo que FilenameUtils.removeExtension()do Apache Commons IO, como sugere a resposta mais votada . Só queria salientar que o Goiaba também faz isso. Pessoalmente, não queria adicionar dependência ao Commons - o que considero uma relíquia - por causa disso.)


2
na verdade, é mais parecido comFilenameUtils.getBaseName()
Angelo.Hannes

na verdade, goiaba é uma lib tão instável que evito usá-la sempre que posso. preferem uma relíquia estável do que experimentos por googel
Slava

8

Abaixo está a referência em 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);
    }
}

1
Informações legais, mas os usuários, estejam cientes de casos como ".htaccess", em que esse método retornará "".
Markus Schulte

6

Se você não gosta de importar os apache.commons completos, extraí a mesma funcionalidade:

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

4

Embora eu acredite em reutilizar bibliotecas, o JAR do org.apache.commons.io tem 174 KB, o que é notavelmente grande para um aplicativo móvel.

Se você baixar o código-fonte e dar uma olhada na classe FilenameUtils, poderá ver muitos utilitários extras, e ele lida com os caminhos do Windows e do Unix, o que é adorável.

No entanto, se você quiser apenas alguns métodos de utilidade estática para uso com caminhos de estilo Unix (com um separador "/"), poderá achar o código abaixo útil.

O removeExtensionmétodo preserva o restante do caminho junto com o nome do arquivo. Há também um semelhante 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;
}

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

1

A maneira mais simples de obter o nome do caminho relativo ou do caminho completo é usando

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


0

Você pode dividir por "." e no índice 0 é o nome do arquivo e em 1 é a extensão, mas eu gostaria da melhor solução com FileNameUtils do apache.commons-io, como foi mencionado no primeiro artigo. Não precisa ser removido, mas é suficiente:

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


0

Use FilenameUtils.removeExtensiondo Apache Commons IO

Exemplo:

Você pode fornecer o nome completo do caminho ou apenas o nome do arquivo .

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

Espero que isto ajude ..


Isso já está na resposta aceita, qual é o objetivo deste post?
Tom

0

A maneira fluente:

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

0

Para simplificar, use o método String.replaceAll () do Java da seguinte maneira:

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

Isso também funciona quando fileNameWithExt inclui o caminho completo.


0

Você pode usar a função java split para dividir o nome do arquivo da extensão, se tiver certeza de que existe apenas um ponto no nome do arquivo para a extensão.

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

então o split[0]retornará "test" e o split [1] retornará "txt"


-3

Experimente o código abaixo. Usando funções básicas do Java. Ele cuida de Strings com extensão e sem extensão (sem o '.'caractere). O caso de múltiplo '.'também é coberto.

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

Você pode adaptá-lo para trabalhar com nullstrings.


1
É uma prática muito ruim implementar esse tipo de funcionalidade você mesmo. À primeira vista, a tarefa parece ser extremamente óbvia , mas, na prática, você enfrentará muitas situações excepcionais (como não há .nome no arquivo, ou arquivo é um backup e tem nome como document.docx.backup, etc). É muito mais confiável usar uma biblioteca externa que lida com todas essas situações excepcionais para você.
amigos estão dizendo sobre ivstas

1
Por outro lado, adicionar muitas bibliotecas ao seu projeto aumentará. Coisas simples assim podem ser feitas por você.
Nicolas Tyler

1
De jeito nenhum você deve fazer isso sozinho. Isso é difícil: arquivos sem extensão, mas. no caminho, caminhos ftp, barras e barras unix, links simbólicos etc ... Você certamente falhará e, ao tentar ganhar um pouco de memória, você terá muita instabilidade. No mínimo, copie as fontes do código estabelecido, se as licenças permitirem.
Jonathan Nappee

Este código se parece com o de Amit Mishra, exceto pelo intimidador 'if (! Str.contains ("."))' '
Broken_Window 13/04/16

falharia no seguinte caso "/someFolder/some.other.folder/someFileWithoutExtention". Primeira coisa que me ocorreu depois de 2 segundos. Tenho certeza de que poderia criar uma tonelada de outros exemplos.
Newtopian 26/09/16
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.