DIVIDIR UNA TIRA

Quan vaig començar a treballar amb Java em vaig trobar amb una desagradable sorpresa. Les funcions per al tractament de tires de caràcter eren poques i, sovint, poc potents. Jo havia programat força amb Rexx i estava molt satisfet de les seves funcions de tractament de tires. De fet, anys després, vaig acabar reproduïnt les funcions de tires de caràcters de Rexx en Java (les podeu descarregar aquí).

Però el meu desencís va ser total quan vaig haver de tallar una tira de caràcters que contenia camps delimitats per comes. La única solució que vaig trobar va ser la classe StringTokenizer, però, en contra de l'opinió de Sun, jo li trobava (i li trobo) un error greu. M'explicaré. Si tenim la tira "a,b,c" i la volem tallar basant-nos en la coma com a delimitador, podíem intentar una cosa similar a aquesta:

String input = "a,b,c";

StringTokenizer st = new StringTokenizer(input, ",");
while (st.hasMoreTokens()) {
  System.out.println("'" + st.nextToken() + "'");
}

El resultat és correcte: 'a' 'b' 'c'.

També ho és si la tira a dividir és"a,b, ,c" ja que ens dóna 'a', 'b', ' ', 'c'.

Els problemes comencen quan la tira a dividir és, per exemple, "a,b,,c" ja que només ens torna tres subtires: 'a', 'b', 'c'. Passa tres quatrs del mateix si la tira a dividir és "a,b,c,". En tots dos casos es deixa una subtira buida per comptar. Si estem processant un fitxer que conté el resultat de l'exportació dels registres d'una taula en format delimitat, aquests camps que StringTokenizer ignora alegrement, poden correspondre a valors null de camps de la taula. Per tant, mai no podríem importar correctament aquest fitxer a una altra taula.

Durant força temps, Sun ha considerat que aquest és el comportament correcte i no ha emprès cap modificació a la classe StringTokenizer.

Finalment, però, la versió 1.4 del JDK ens proporciona una solució al problema (consti que la classe StringTokenizer es continua comportant tan malament com sempre) mitjançant la incorporació de les expressions regulars.

No entraré aquí en els detalls de la sintaxi de les expressions regulars. Dir només que la classe String les incorpora de manera agradable en alguns dels seus nous mètodes.

Doncs bé, la manera correcta de tallar una tira basant-se en els delimitadors podria ser aquesta:

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 resultat, en aquest cas, seria correcte: 'a', 'b', 'c', ''; és a dir, quatre subtires i la quarta buida.

Fixem-nos que el mètode split() s'invoca amb dos paràmetres. El primer és el delimitador (que pot ser molt més complicat, ja que és un patró d'expressions regulars) i el segon és un enter que indica el nombre de vegades que s'aplicarà el patró a la tira. Si té un valor positiu, s'aplicarà tantes vegades com indiqui aquest paràmetre. Així, si la tira a dividir és 'a', 'b', 'c' i especifiquem 2, obrindrem només dues subtires: 'a' i 'bc'. Si l'enter és negatiu, com en el nostre exemple, s'aplicarà tantes vegades com li sigui possible. Si és zero (0) també s'aplicarà tantes vegades com sigui possible, però les tires finals buides no es tenen en compte. Aixi, en el nostre exemple, obtindríem només tres subtires. Per tant, ens interessa especificar un número negatiu.

Espero que aquest truc us sigui d'utilitat!