Cadena dividida con un punto como delimitador

99

Me pregunto si voy a dividir una cuerda de .la manera correcta. Mi codigo es:

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

Solo necesito la primera parte de la cadena, por eso devuelvo el primer elemento. Pregunto porque noté en la API que .significa cualquier carácter, así que ahora estoy atascado.

Decano
fuente

Respuestas:

173

split()acepta una expresión regular, por lo que debe escapar .para no considerarla como un metacarácter regex. He aquí un ejemplo:

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

Split usa expresiones regulares, donde '.' es un carácter especial que significa cualquier cosa. Necesita escapar de él si realmente quiere que coincida con el '.' personaje:

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

(uno '\' para escapar del '.' en la expresión regular y el otro para escapar del primero en la cadena de Java)

Además, no sugeriría devolver fn [0] ya que si tiene un archivo con nombre something.blabla.txt, que es un nombre válido, no devolverá el nombre de archivo real. En cambio, creo que es mejor si usa:

int idx = filename.lastIndexOf('.');
return filename.subString(0, idx);
Andrei Fierbinteanu
fuente
La pregunta está etiquetada como Java, no Javascript, que es a lo que se vinculó.
Andrei Fierbinteanu
17

Veo solo soluciones aquí pero no una explicación completa del problema, así que decidí publicar esta respuesta

Problema

Necesitas saber algunas cosas sobre text.split(delim). splitmétodo:

  1. acepta como argumento la expresión regular (regex) que describe el delimitador en el que queremos dividir,
  2. if delimexiste al final de textlike en a,b,c,,(donde está el delimitador ,) splital principio creará una matriz como, ["a" "b" "c" "" ""]pero como en la mayoría de los casos no necesitamos estas cadenas vacías finales, también las elimina automáticamente para nosotros. Entonces crea otra matriz sin estas cadenas vacías finales y la devuelve .

También necesita saber que el punto. es un carácter especial en expresiones regulares . Representa cualquier carácter (excepto los separadores de línea, pero esto se puede cambiar con una Pattern.DOTALLbandera).

Entonces, para cadenas como "abc"si dividiéramos el "." splitmétodo,

  1. crear una matriz como ["" "" "" ""],
  2. pero dado que esta matriz contiene solo cadenas vacías y todas están al final, se eliminarán (como se muestra en el segundo punto anterior)

lo que significa que obtendremos como resultado una matriz vacía [](sin elementos, ni siquiera una cadena vacía), por lo que no podemos usar fn[0]porque no hay índice 0.

Solución

Para resolver este problema, simplemente necesita crear una expresión regular que represente un punto. Para hacerlo, tenemos que escapar de eso .. Hay pocas maneras de hacerlo, pero más sencilla es probablemente usando \(que en la cadena necesita ser escrita como "\\"porque \también es especial y no requiere otro \que se escapó).

Entonces, la solución a su problema puede parecer

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

Prima

También puedes usar otras formas de escapar de ese punto como

  • usando la clase de personaje split("[.]")
  • envolviéndolo en una cita split("\\Q.\\E")
  • usando la instancia de patrón adecuada con Pattern.LITERALbandera
  • o simplemente use split(Pattern.quote("."))y deje que regex se escape por usted.
Pshemo
fuente
esto .. Me gusta mucho el: split("[.]")
Dragonborn
15

el método String # split (String) usa expresiones regulares. En expresiones regulares, el "." carácter significa "cualquier carácter". Puede evitar este comportamiento escapando del "."

filename.split("\\.");

o decirle al método split que se divida en una clase de carácter:

filename.split("[.]");

Las clases de personajes son colecciones de personajes. Podrías escribir

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

y el nombre del archivo se dividiría en cada "-", ".", ";", "l", "d" o "7". Dentro de las clases de caracteres, el "." no es un carácter especial ("metacarácter").

f1sh
fuente
@MisterSmith Es posible que desee echar un vistazo al lenguaje de programación aquí. Estamos hablando de java, no de javascript.
f1sh
Tienes toda la razón. Ayer estaba cansado, habiendo estado codificando en ambos lenguajes, no noté los tipos de datos de Java. Pensé que quizás las respuestas eran correctas en 2010, pero de alguna manera los navegadores actuales se comportaron de manera diferente.
Mister Smith
7

Como DOT (.) Se considera un carácter especial y el método de división de String espera una expresión regular que debe hacer así:

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

En Java, los caracteres especiales deben escaparse con un "\", pero dado que "\" también es un carácter especial en Java, ¡debe escapar de nuevo con otro "\"!

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

¿No sería más eficiente usar

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

si solo quieres lo que pasa hasta el primer punto?

Martin Smith
fuente
2

Por lo general, NO es una buena idea desenmascararlo a mano. Hay un método en la clase Pattern para esta tarea:

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

La división debe tomar regex como argumento ... Simplemente cambie "."a"\\."

Bob Fincheimer
fuente
0

Nota: Se debe tener más cuidado con este fragmento, incluso después de que se haya escapado el punto.

Si el nombre del archivo es solo la cadena ".", Entonces fn terminará teniendo una longitud 0 y fn [0] aún generará una excepción.

Esto se debe a que si el patrón coincide al menos una vez, la división descartará todas las cadenas vacías finales (¡por lo tanto, también la que está antes del punto!) De la matriz, dejando una matriz vacía para devolver.

avl42
fuente
La solución más sencilla en casos como el que nos ocupa es pasar también un argumento límite de 2 a la llamada a dividir: String [] fn = filename.split ("[.]", 2);
avl42
0

La solución que funcionó para mí es la siguiente

nombrearchivo.split ("[.]");

jorge santos
fuente
0

Usar ApacheCommons es más simple:

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

Tenga en cuenta que también extrae un nombre de archivo de la ruta completa.

Nikita
fuente
-2

splittoma una expresión regular como argumento. Por lo tanto, debe pasar en "\."lugar de "."porque "."es un metacarácter en expresiones regulares.

Vijay Mathew
fuente