Como aparar uma extensão de arquivo de uma String em Java?

176

Qual é a maneira mais eficiente de aparar o sufixo em Java, assim:

title part1.txt
title part2.html
=>
title part1
title part2
AMD
fonte
2
código eficiente sábio, é o que você quer dizer eu espero, não CPU sábio
mkoryak
3
Ele não estava perguntando como fazê-lo, estava perguntando qual era a maneira mais eficiente. Eu vim aqui procurando a mesma coisa.
Edward Falk

Respostas:

285

Este é o tipo de código que não deveríamos estar fazendo nós mesmos. Use bibliotecas para as coisas mundanas, salve seu cérebro para as coisas difíceis.

Nesse caso, eu recomendo usar FilenameUtils.removeExtension () do Apache Commons IO

skaffman
fonte
7
Absolutamente bang.
Joshua Pinter
6
Para 95% dos projetos, essa deve ser a resposta aceita. Reescrever códigos como esse é a causa raiz de muitas dores de cabeça!
Carsten Hoffmann
1
Basta adicionar a seguinte linha em gradle para adicionar a impedância: - compile 'commons-io: commons-io: 2.6'
Deepak Sharma
exemplo por favor.
john ktejik
8
Se você já possui o Apache Commons I / O em seu projeto, isso mesmo. Mas, se tudo isso for necessário, você estará adicionando (pelo menos) 2,5 MB de peso morto ao seu projeto para algo que pode ser feito facilmente com uma única linha.
foo
226
str.substring(0, str.lastIndexOf('.'))
Svitlana Maksymchuk
fonte
8
Isso deve ser atribuído a uma nova variável, pois str não é modificado.
197 Nathan Feger
51
Manuseie com cuidado: ele emitirá uma exceção se o nome do arquivo não tiver sufixo.
Andreas Dolk
24
e quanto a archive.tar.bz2?
Antonio
20
if(str.contains(".")) str.substring(0, str.lastIndexOf('.'))
Nicolas Tyler
6
if (str! = null && str.contains (".")) str.substring (0, str.lastIndexOf ('.')). FilenameUtils é outra dependência, e não sempre disponível
ocramot
88

Como usar o String.substringe String.lastIndexem uma linha é bom, existem alguns problemas em termos de capacidade de lidar com certos caminhos de arquivo.

Pegue, por exemplo, o seguinte caminho:

a.b/c

O uso de uma linha resultará em:

a

Isso está incorreto.

O resultado deveria ter sido c, mas como o arquivo não tinha extensão, mas o caminho tinha um diretório com a .no nome, o método de uma linha foi enganado para fornecer parte do caminho como o nome do arquivo, o que não está correto.

Necessidade de cheques

Inspirado pela resposta de skaffman , dei uma olhada no FilenameUtils.removeExtensionmétodo do Apache Commons IO .

Para recriar seu comportamento, escrevi alguns testes que o novo método deve executar, que são os seguintes:

Nome do arquivo do caminho
-------------- --------
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

(E foi tudo o que eu verifiquei - provavelmente há outras verificações que devem ser feitas e que eu ignorei.)

A implementação

A seguir está minha implementação para o 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);
}

A execução desse removeExtensionmétodo com os testes acima produz os resultados listados acima.

O método foi testado com o seguinte código. Como isso foi executado no Windows, o separador de caminho é aquele \que deve ser escapado com um \quando usado como parte de um 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"));

Os resultados foram:

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

Os resultados são os resultados desejados descritos no teste que o método deve cumprir.

coobird
fonte
4
Ótima resposta. Existe uma razão específica para você usar System.getProperty("file.separator")e não apenas File.separator?
halirutan
2
Uma palavra de aviso: Esta solução também remove o caminho anterior, não apenas a extensão, ao contrário do método Apache Commons IO.
DHA
3
Parece que este irá falhar para o/path/to/.htaccess
Kuzeko
17

BTW, no meu caso, quando eu queria uma solução rápida para remover uma extensão específica, foi o que fiz aproximadamente:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;
Edward Falk
fonte
16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));
Jherico
fonte
4
Não, pode haver mais de um '.'; você quer lastIndexOf ( '')
Adam Jaskiewicz
-1 por não usar o método que pensei que estava usando. Agora é um total de +0 de mim. Mude 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);
}

Esta é uma pergunta complicada? : p

Não consigo pensar em uma maneira mais rápida de atm.

Huxi
fonte
7

Use um método em com.google.common.io.Filessala de aula se seu projeto já estiver dependente da biblioteca principal do Google. O método que você precisa é getNameWithoutExtension.

Toby
fonte
Por que alguém é contra a minha resposta?
Toby
Observe que isso retorna apenas o nome da base; portanto, o caminho também é removido: google.github.io/guava/releases/19.0/api/docs/com/google/common/…
thSoft
6

você pode tentar esta função, muito básica

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

Achei a resposta do coolbird particularmente útil.

Mas mudei as últimas instruções de resultado para:

if (extensionIndex == -1)
  return s;

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

como eu queria que o nome do caminho completo fosse retornado.

Assim, "C: \ Users \ mroh004.COM \ Documents \ Test \ Test.xml" se torna 
   "C: \ Users \ mroh004.COM \ Documents \ Test \ Test" e não
   "Teste"
mxro
fonte
5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();
Alexander
fonte
3
Ao contrário do que foi perguntado e não há necessidade de passar o comprimento, é só usar um ARG substring
4

Use uma regex. Este substitui o último ponto e tudo depois dele.

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

Você também pode criar um objeto Pattern se desejar pré-compilar o regex.

Steven Spungin
fonte
1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");
Mahdak
fonte
Precisa dividir "\\."como "." é especial para regex.
Compass
1

crie um novo arquivo com o caminho da imagem da string

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

org.apache.commons.io.FilenameUtils versão 2.4 fornece a seguinte resposta

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 = '\\';
Alguém algum lugar
fonte
1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }
Super Nova
fonte
0

Eu faria assim:

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

Do início ao fim até o '.' depois chame a substring.

Edit: Pode não ser um golfe, mas é eficaz :)

fmsf
fonte
7
Isso é basicamente o que lastIndexOf faz de qualquer maneira; por que reinventar a roda?
Michael Myers
Por diversão e para ser um pouco descritivo. só isso. (e eu esqueci lastIndexOf quando eu estava escrevendo este)
FMSF
0

Tendo em mente os cenários em que não há extensão de arquivo ou há mais de uma extensão de arquivo

exemplo Nome do arquivo: arquivo | arquivo.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
fonte
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();
}

Isso produzirá exemplo para img e imgLink

urs86ro
fonte
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
fonte
Isso transformará "a.jpg.jpg" em "a" em vez de (correto) "a.jpg". Que finalidade serve para o file.length() > 0cheque?
Klaus Gütter 12/01/19
A questão principal era "como remover a extensão?", Então sim, sua transformação "a.txt.zip" para "a" e ".htaccess" para o vazio. Essa função funciona com Strings, portanto, os nomes dos arquivos não podem ser nulos, mas ainda podem ter um comprimento 0, verificar mais rapidamente se vale a pena antes de analisar os símbolos. Saudações.
Alexey