Cuando empecé a trabajar en Java, me encontré con una desagradable sorpresa. Las funciones para el manejo de tiras de caracteres eran pocas y, con frecuencia, poco potentes. Yo había programado bastante en Rexx y estaba muy satisfecho de sus funciones de manejo de tiras. De hecho, años después, acabé reproducioendo las funciones de tiras de caracteres de Rexx en Java (las podéis descargar aquí).
Pero mi decepción fue total cuando tuve que cortar una tira de caracteres
que contenía campos delimitados por comas. La única solución que encontré fue
la clase StringTokenizer
, pero, en contra de la opinión de Sun,
yo le encontraba (y le encuentro) un error grave. Me explicaré. Si tenemos
la tira "a,b,c"
y la queremos cortar basándonos en la coma como
delimitador, podríamos intentar algo parecido a esto:
String input = "a,b,c"; StringTokenizer st = new StringTokenizer(input, ","); while (st.hasMoreTokens()) { System.out.println("'" + st.nextToken() + "'");
}
El resultado es correcto: 'a' 'b' 'c'
.
También lo es si la tira a dividir es"a,b, ,c"
ya
que nos da 'a', 'b', ' ', 'c'
.
Los problemas empiezan cuando la tira a dividir es, por ejemplo, "a,b,,c"
ya
que sólo nos devuelve tres subtiras: 'a', 'b', 'c'
. Pasa
tres cuartos de lo mismo si la tira a dividir es "a,b,c,"
.
En ambos casos, se deja una tira vacía por contar. Si estamos procesando un
archivo que contiene el resultado de la exportación de los registros de una
tabla en formato delimitado, estos campos que StringTokenizer
ignora
alegremente, pueden corresponder a valores null
de campos de la
tabla. Por lo tanto, nunca podríamos importar correctamente este archivo a
otra tabla.
Durante bastante tiempo, Sun ha considerado que éste es el comportamiento
correcto y no ha emprendido ninguna modificación de la clase StringTokenizer
.
Finalmente, sin embargo, la versión 1.4 del JDK nos proporciona la solución
al problema (conste que la clase StringTokenizer
se continúa comportando
tan mal como siempre) mediante la incorporación de las expresiones
regulares.
No entraré aquí en los detalles de la sintaxis de las expresiones regulares.
Decir, tan solo, que la clase String
las incorpora de manera agradable
en algunos de sus nuevos métodos.
Pues bien, la manera correcta de cortar una tira basándose en los delimitadores podría ser esta:
String input = "a,b,c,";
String delimiter = ",";
String[] fields = input.split(delimiter, -1);
for (int i = 0; i < fields.length; i++) { System.out.println("'" + fields[i] + "'");
}
El resultado, en este caso, sería correcto : 'a', 'b', 'c', ''
;
es decir, cuatro subtiras y la cuarta vacía.
Obsérvese que el método split()
se invoca con dos
parámetros. El primero es el delimitador (que puede ser más complicado, ya
que es un patrón de expresiones regulares) y el segundo es un entero que indica
el número de veces que se aplicará el patrón a la tira. Si tiene un valor positivo,
se aplicará tantas veces como indique este parámetro. Así, si la tira a dividir
es 'a', 'b', 'c'
y especificamos 2, obtendremos sólo dos subtiras: 'a'
y 'bc'
.
Si el entero es negativo, como en nuestro ejemplo, se aplicará tantas veces
como sea posible. Si es cero (0)
también se aplicará tantas veces como sea posible, pero las tiras finales vacías
no se tendrán en cuenta. Así, en nuestro ejemplo, obtendríamos solamente tres
subtiras. Por consiguiente, nos interesa especificar un número negativo.
¡Espero que este truco os sea de utilidad!