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.

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

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

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ê.

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


@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 "\"!



2

Não seria mais eficiente usar

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

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


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) 

1

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


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.


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


0

Usar ApacheCommons é mais simples:

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

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


-2

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

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.