Divida a string com um ponto como delimitador

99

Estou me perguntando se vou rachar uma corda .da maneira certa. Meu código é:

String[] fn = filename.split(".");
return fn[0];

Só preciso da primeira parte da string, por isso devolvo o primeiro item. Eu pergunto porque percebi na API que .significa qualquer personagem, então agora estou preso.

reitor
fonte

Respostas:

173

split()aceita uma expressão regular, portanto, você precisa escapar .para não considerá-la como um metacaractere regex. Aqui está um exemplo:

String[] fn = filename.split("\\."); 
return fn[0];
Marimuthu Madasamy
fonte
17

A divisão usa expressões regulares, onde '.' é um caractere especial que significa qualquer coisa. Você precisa escapar dela se realmente quiser que corresponda a '.' personagem:

String[] fn = filename.split("\\.");

(um '\' para escapar de '.' na expressão regular e o outro para escapar do primeiro na string Java)

Além disso, eu não sugeriria retornar fn [0], pois se você tiver um arquivo chamado something.blabla.txt, que é um nome válido, você não retornará o nome real do arquivo. Em vez disso, acho melhor se você usar:

int idx = filename.lastIndexOf('.');
return filename.subString(0, idx);
Andrei Fierbinteanu
fonte
A pergunta é Java, não Javascript, que é o link ao qual você fez o link.
Andrei Fierbinteanu
17

Vejo apenas soluções aqui, mas nenhuma explicação completa do problema, então decidi postar esta resposta

Problema

Você precisa saber algumas coisas sobre text.split(delim). splitmétodo:

  1. aceita como argumento a expressão regular (regex) que descreve o delimitador no qual queremos dividir,
  2. se delimexiste no final de textlike in a,b,c,,(onde o delimitador é ,) splita princípio criará um array like, ["a" "b" "c" "" ""]mas como na maioria dos casos não precisamos realmente dessas strings vazias, ele também as remove automaticamente para nós. Portanto, ele cria outro array sem essas strings vazias no final e o retorna .

Você também precisa saber que o ponto. é um caractere especial no regex . Ele representa qualquer caractere (exceto separadores de linha, mas isso pode ser alterado com o Pattern.DOTALLsinalizador).

Então, para strings como "abc"se dividíssemos no "." splitmétodo,

  1. criar matriz como ["" "" "" ""],
  2. mas como esta matriz contém apenas strings vazias e todas elas estão no final, elas serão removidas (como mostrado no segundo ponto anterior)

o que significa que obteremos como resultado um array vazio [](sem elementos, nem mesmo uma string vazia), então não podemos usar fn[0]porque não há índice 0.

Solução

Para resolver este problema, você simplesmente precisa criar um regex que representará o ponto. Para fazer isso, precisamos escapar disso .. Existem algumas maneiras de fazer isso, mas a mais simples é provavelmente usando \(que em String precisa ser escrito "\\"porque \também é especial lá e requer que outro \tenha escape).

Portanto, a solução para o seu problema pode parecer

String[] fn = filename.split("\\.");

Bônus

Você também pode usar outras maneiras de escapar desse ponto, como

  • usando classe de personagem split("[.]")
  • envolvendo-o em citação split("\\Q.\\E")
  • usando a instância de padrão adequada com Pattern.LITERALbandeira
  • ou simplesmente use split(Pattern.quote("."))e deixe o regex fazer o escape para você.
Pshemo
fonte
isso .. Eu realmente gosto de: split("[.]")
Dragonborn
15

o método String # split (String) usa expressões regulares. Em expressões regulares, o "." caractere significa "qualquer caractere". Você pode evitar esse comportamento escapando de "."

filename.split("\\.");

ou dizendo ao método de divisão para dividir em uma classe de caracteres:

filename.split("[.]");

As classes de personagens são coleções de personagens. Você poderia escrever

filename.split("[-.;ld7]");

e o nome do arquivo seria dividido a cada "-", ".", ";", "l", "d" ou "7". Dentro das classes de personagens, o "." não é um caractere especial ("metacaractere").

f1sh
fonte
@MisterSmith Você pode querer dar uma olhada na linguagem de programação aqui. Estamos falando de java, não javascript.
f1sh
Você está absolutamente certo. Eu estava cansado ontem, por estar programando nas duas linguagens, não notei os tipos de dados Java. Achei que talvez as respostas estivessem corretas em 2010, mas de alguma forma os navegadores de hoje se comportaram de maneira diferente.
Senhor Smith
7

Como DOT (.) É considerado um caractere especial e o método de divisão de String espera uma expressão regular que você precisa fazer assim -

String[] fn = filename.split("\\.");
return fn[0];

Em java, os caracteres especiais precisam ser escapados com um "\", mas como "\" também é um caractere especial em Java, você precisa escapá-lo novamente com outro "\"!

Neel
fonte
3
String str="1.2.3";
String[] cats = str.split(Pattern.quote("."));
Magnus Persson
fonte
2

Não seria mais eficiente usar

 filename.substring(0, filename.indexOf("."))

se você só quer o que vai até o primeiro ponto?

Martin Smith
fonte
2

Normalmente NÃO é uma boa ideia desmascará-lo manualmente. Existe um método na classe Pattern para esta tarefa:

java.util.regex
static String quote(String s) 
Christian Ullenboom
fonte
1

A divisão deve ter regex como um argumento ... Simplesmente mude "."para"\\."

Bob Fincheimer
fonte
0

Nota: Cuidado adicional deve ser tomado com este snippet, mesmo depois que o ponto for escapado!

Se o nome do arquivo for apenas a string ".", Então fn ainda terá comprimento 0 e fn [0] ainda lançará uma exceção!

Isso porque, se o padrão corresponder pelo menos uma vez, a divisão descartará todas as strings vazias posteriores (portanto, também aquela antes do ponto!) Do array, deixando um array vazio para ser retornado.

avl42
fonte
a solução mais fácil em casos como o que temos em mãos é também passar um argumento-limite de 2 para a chamada para dividir: String [] fn = filename.split ("[.]", 2);
avl42
0

A solução que funcionou para mim é a seguinte

filename.split ("[.]");

Jorge Santos
fonte
0

Usar ApacheCommons é mais simples:

File file = ...
FilenameUtils.getBaseName(file.getName());

Observe que também extrai um nome de arquivo do caminho completo.

Nikita
fonte
-2

splitleva uma regex como argumento. Portanto, você deve passar em "\."vez de "."porque "."é um metacaractere no regex.

Vijay Mathew
fonte