Las aplicaciones que manipulan texto necesitan localizar l�mites dentro del propio texto. Por ejemplo, consideremos algunas de las funciones comunes en un procesador de textos: iluminar un caracter, cortar una palabra, mover el cursor al p�rrafo siguiente, y cortar las palabras al final de la l�nea. Para realizar cada una de estas funciones, el procesador de textos debe poder detectar los l�mites l�gicos del texto. Afortunadamente, no tenemos que escribir nuestras propias rutinas para realizar an�lisis de l�mites. En su lugar, podemos aprovecharnos de los m�todos propocionados por la clase BreakIterator.
�Sobre la clase BreakIterator
Esta secci�n explica la ejemplarizaci�n de m�todos y los cursores imaginarios de la clase BreakIterator.
clase BreakIterator es sensible a la Localidad, porque los l�mites de texto pueden variar con el idioma. Por ejemplo, la reglas para ruptura de l�neas no son las mismas para todos los idiomas. Para determinar las Localidades soportadas por la clase BreakIterator se llama al m�todo getAvailableLocales.
Locale[] locales = BreakIterator.getAvailableLocales();
Se pueden analizar cuatro tipos diferentes de l�mites con la clase BreakIterator: caracter, palabra, p�rrafo y ruptura potencial de l�nea. Cuande se ejemplariza un BreakIterator, se debe llamar al m�todo de creacci�n apropiado.
- getCharacterInstance
- getWordInstance
- getSentenceInstance
- getLineInstance
Cada ejemplar de BreakIterator s�lo puede detectar un tipo de l�mite. Si se quiere localizar el l�mite de caracter y de palabra, por ejemplo, se necesitar� crear dos ejemplares separados.
Un BreakIterator tiene un cursor imaginario que apunta al l�mite actual en una cadena de texto. Se puede mover este cursor dentro del texto con los m�todos previous y next. Por ejemplo, si hemos creado un BreakIterator con getWordInstance, cada vez que llamemos al m�todo next el cursor de mover� al siguiente l�mite de palabra dentro del texto. Los m�todos de movimiento del cursor devuelven un entero indicando la posici�n del l�mite. Esta posici�n es el �ndice del caracter de la cadena de texto que sigue al l�mite. Al igual que los Strings indexados, los l�mites est�n basados en cero. El primer l�mite es el 0, y el �ltimo l�mite es la longitud de la cadena.
Se deber�a utilizar la clase BreakIterator s�lo con texto natural. No se debe utilizar con lenguajes de programaci�n.
En las siguientes secciones, proporcionaremos ejemplos de cada tipo de l�mite. Los ejemplos de c�digo se han extraido de un fichero llamado BreakIteratorDemo.java.
�L�mite de Caracter
En esta secci�n aprender�s la diferencia entre los caracteres de usuario y los caracteres Unicode, y como localizar los caracteres de usuario con un BreakIterator.
necesitar� localizar los l�mites de caracter si nuestra aplicaci�n permite al usuario final seleccionar caracteres individuales. o mover el cursor a trav�s del texto caracter a caracter. Para crear un BreakIterator que localice los l�mites de caracter se llama al m�todo getCharacterInstance.
BreakIterator characterIterator = BreakIterator.getCharacterInstance(currentLocale);
Este tipo de BreakIterator detecta l�mites entre caracteres de usuario, no s�lo caracteres Unicode. Los caracteres de usuario var�an con el idioma, pero la clase BreakIterator puede reconocer estas diferencias porque es sensible a la Localidad. Un caracter de usuario podr�a estar compuesto por uno o m�s caracteres Unicode. Por ejemplo, el caracter de usuario � podr�a componerse combinando los caracteres Unicode '\u0075' (u) '\u00a8' (�). Sin embargo, este no es el mejor ejemplo, porque el caracter � tambi�n podr�a ser represetnado por un s�lo caracter Unicode '\u00fc'. Veremos el idioma �rabe para un ejemplo m�s realista.
En �rabe, la palabra para casa es.

Aunque esta palabra contiene tres caracteres de usuario, est� compuesta por seis caracteres Unicode.
String house = "\u0628" + "\u064e" + "\u064a" + "\u0652" + "\u067a" + "\u064f";
Los caracteres Unicode de las posiciones 1,3 y 5 en la cadena house son diacr�ticos. En �rabe los diacr�ticos son necesarios, porque pueden alterar el significado de las palabras. Los diacr�ticos en nuesto ejemplo son caracteres no blancos ya que aparecen sobre los caracteres base. En un procesador de textos �rabe, no podemos mover el cursor sobre cada caracter Unicode de la cadena. En su lugar, debemos movernos sobre cada caracter de usuario, que podr�a estar compuesto por m�s de un caracter Unicode. Por lo tanto, debemos utilizar un BreakIterator para scanear los caracteres de usuario en la cadena.
En nuestro ejemplo, BreakIteratorDemo.java, hemos creado un BreakIterator para scanear caracteres ar�bicos. Luego pasamos este BreakIterator, junto con el objeto String creado anteriormente, al m�todo llamado listPositions.
BreakIterator arCharIterator = BreakIterator.getCharacterInstance(new Locale ("ar","SA")); listPositions (house,arCharIterator);
El m�todo listPositions utiliza un BreakIterator para localizar los l�mites de caracter dentro de la cadena. Observa que asignamos un string particular al BreakIterator con el m�todo setText. Recuperamos el primer l�mite de caracter con el m�todo first, luego llamamos al m�todo next hasta que se devuelva la constante BreakIterator.DONE. Aqu� podemos ver el c�digo de esta rutina.
static void listPositions(String target, BreakIterator iterator) { iterator.setText(target); int boundary = iterator.first(); while (boundary != BreakIterator.DONE) { System.out.println (boundary); boundary = iterator.next(); } }
El m�todo listPositions imprime las siguientes posiciones de l�mites para los caracteres de usuario de la cadena house. Las posiciones de los diacr�ticos (1, 3, 5) no se listan.
0 2 4 6
�L�mite de Palabra
Si la aplicaci�n necesita seleccionar o lacalizar palabras dentro del texto, encontraremos util el uso de un BreakIterator.
invoca al m�todo getWordIterator para ejemplarizar un BreakIterator que detecte l�mites de palabra.
BreakIterator wordIterator = BreakIterator.getWordInstance(currentLocale);
Querremos crear un BreakIterator como �ste cuando nuestras aplicaciones necesiten realizar operaciones con palabras individuales. Estas operaciones podr�an ser las funciones comunes de los procesadores de textos como selecionar, cortar, pegar y copiar. O nuestras aplicaciones podr�an buscar palabras, y para hacer esto necesitan poder distinguir entre palabras completas.
Cuando se realizan an�lisis de l�mites de palabra, un BreakIterator diferencia entre las palabras y los caracteres que no forman parte de las palabras. Estos caracteres, que incluyen espacios, tabuladores, marcas de puntuaci�n, y algunos s�mbolos, tienen l�mites de palabras en �mbos lados.
En el siguiente ejemplo, extraido del programa BreakIteratorDemo.java, queremos marcar los l�mites de palabras en alg�n texto. Primero creamos el BreakIterator y luego llamamos a un m�todo que hemos escrito llamado markBoundaries.
Locale currentLocale = new Locale ("en","US"); BreakIterator wordIterator = BreakIterator.getWordInstance(currentLocale); String someText = "She stopped. " + "She said, \"Hello there,\" and then went on."; markBoundaries(someText, wordIterator);
El prop�sito de este m�todo es marcar los l�mites de palabras en un string con un caracter ('^'). Cada vez que BreakIterator detecta un l�mite palabra, insertamos este caracter en el buffer markers. Scaneamos el string en un bucle, llamando al m�todo next hasta que devuelva BreakIterator.DONE. Aqu� tenemos el c�digo de la rutina markBoundaries.
static void markBoundaries(String target, BreakIterator iterator) { StringBuffer markers = new StringBuffer(); markers.setLength(target.length() + 1); for (int k = 0; k < markers.length(); k++) { markers.setCharAt(k,' '); } iterator.setText(target); int boundary = iterator.first(); while (boundary != BreakIterator.DONE) { markers.setCharAt(boundary,'^'); boundary = iterator.next(); } System.out.println(target); System.out.println(markers); }
El m�todo markBoundaries imprime el string target y el buffer markers. Obseva donde ocurren los caracteres ('^') en relaci�n con las marcas de puntuaci�n y los espacios.
She stopped. She said, "Hello there," and then went on. ^ ^^ ^^ ^ ^^ ^^^^ ^^ ^^^^ ^^ ^^ ^^ ^
El BreakIterator hace sencilla la selecci�n de palabras dentro de un texto. No tenemos que escribir nuestras propias rutinas para manejar las reglas de puntuaci�n de los distintos idiomas, porque la clase BreakIterator lo hace por nosotros. Aqu� podemos ver una subrutina que extrae e imprime las palabras de una cadena dada.
static void extractWords(String target, BreakIterator wordIterator) { wordIterator.setText(target); int start = wordIterator.first(); int end = wordIterator.next(); while (end != BreakIterator.DONE) { String word = target.substring(start,end); if (Character.isLetterOrDigit(word.charAt(0))) { System.out.println(word); } start = end; end = wordIterator.next(); } }
En nuestro ejemplo, llamamos a extractWords, le pasamos la misma cadena que en el ejemplo anterior. El m�todo extractWords imprimir� la siguiente lista de palabras.
She stopped She said Hello there and then went on.
�L�mites de P�rrafo
Determinar los l�mites de p�rrafo puede ser problem�tico, debido a la utilizaci�n ambigua de terminadores de sentecias en muchos idiomas escritos. Esta secci�n examina algunos de los problemas que podremos encontrarnos, y como tratarlos con la clase BreakIterator.
En muchos idiomas el terminador de sentencia es un punto. En Ingl�s, tambi�n se utiliza un punto para especificar el separador decimal, para indicar una marca de elipsis, y para terminar abreviaturas. C�mo el punto tiene m�s de un prop�sito, no podemos determinar el l�mite se sentencia con total seguridad.
Primero, echemos un vistazo a un caso en el que si funciona la detecci�n de l�mite de sentencia. Empezaremos creando un BreakIterator con el m�todo getSentenceInstance.
BreakIterator sentenceIterator = BreakIterator.getSentenceInstance(currentLocale);
Para demostrar los l�mites de sentencias, utilizaremos el m�todo markBoundaries, que se explic� en la secci�n anterior. El m�todo markBoundaries imprime caracteres ('^') en un string para indicar las posiciones de los l�mites. En el siguiente ejemplo, los l�mites de sentencias est�n definidos apropiadamente.
She stopped. She said, "Hello there," and then went on. ^ ^ ^
Tambi�n se pueden localizar los l�mites de sentencias que terminen en interrogaciones o puntos de exaclamaci�n.
He's vanished! What will we do? It's up to us. ^ ^ ^ ^
Utilizar el punto como separador decimal no provoca ning�n error.
Please add 1.5 liters to the tank. ^ ^
Una marca de elipsis (puntos suspensivos) indica la omisi�n de texto dentro de un pasaje entrecomillado. En el siguiente ejemplo los puntos suspensivos generan l�mites de sentencia.
"No man is an island . . . every man . . . " ^ ^ ^ ^ ^ ^^
Las abreviaturas tambi�n podr�an provocar errores. Si el punto es seguido por un espacio en blanco y una letra may�scula, el BreakIterator detecta un l�mite de sentencia.
My friend, Mr. Jones, has a new dog. The dog's name is Spot. ^ ^ ^ ^
�L�mite de L�nea
Esta secci�n describe como localizar las rupturas de l�nea potenciales en una cadena de texto con un BreakIterator.
Las aplicaciones que formatean texto o realizan ruptura de l�neas deben localizar las rupturas de l�neas potenciales. Se pueden encontrar estas rupturas de l�nea, o l�mites, con un BreakIterator que haya sido creado con el m�todo getLineInstance.
BreakIterator lineIterator = BreakIterator.getLineInstance(currentLocale);
Este BreakIterator determina la posici�n en que se puede romper una l�nea para continuar en la siguiente l�nea. Las posiciones detectadas por el BreakIterator son rupturas de l�neas potenciales. La ruptura de l�nea real mostrada en la pantalla podr�a no ser la misma.
En los siguientes ejemplos, utilizamos el m�todo markBoundaries para ver los l�mites de l�nea detectados por un BreakIterator. Este m�todo imprime marcas en los l�mites de l�nea de la cadena fuente.
De acuerdo al BreakIterator, un l�mite de l�nea ocurre despu�s del final de una secuencia de caracteres blancos, (space, tab, newline). En el siguiente ejemplo, podemos romper la l�nea en cualquiera de los l�mites detectados.
She stopped. She said, "Hello there," and then went on. ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
Las rupturas de l�neas potenciales tambi�n ocurren inmediatamente despu�s de un gui�n.
There are twenty-four hours in a day. ^ ^ ^ ^ ^ ^ ^ ^ ^
En el siguiente ejemplo, rompemos una cadena en l�neas de la misma longitud con un m�todo llamado formatLines. Utilizamos un BreakIterator para localizar las rupturas de l�neas potenciales. Para romper una l�nea, ejecutamos un System.out.println() siempre que la longitud de la l�nea actual alcance el valor del par�metro maxLength. El m�todo formatLines es corto, sencillo, y gracias al BreakIterator, independiente de la Localidad. Aqu� puedes ver su c�digo fuente.
static void formatLines(String target, int maxLength, Locale currentLocale) { BreakIterator boundary = BreakIterator.getLineInstance(currentLocale); boundary.setText(target); int start = boundary.first(); int end = boundary.next(); int lineLength = 0; while (end != BreakIterator.DONE) { String word = target.substring(start,end); lineLength = lineLength + word.length(); if (lineLength >= maxLength) { System.out.println(); lineLength = word.length(); } System.out.print(word); start = end; end = boundary.next(); } }
En el programa BreakIteratorDemo.java llamamos a formatLines de esta forma.
String moreText = "She said, \"Hello there,\" and then " + "went on down the street. When she stopped " + "to look at the fur coats in a shop window, " + "her dog growled. \"Sorry Jake,\" she said. " + " \"I didn't know you would take it personally.\""; formatLines(moreText, 30, currentLocale);
Aqu� podemos ver la salida de la llamada a formatLines.
She said, "Hello there," and then went on down the street. When she stopped to look at the fur coats in a shop window, her dog growled. "Sorry Jake," she said. "I didn't know you would take it personally."