lunes, 25 de enero de 2010

Uso de StringTokenizer con varios caracteres separadores (Java)

Java
Todos hemos tenido que utilizar alguna vez StringTokenizer para separar subcadenas a partir de una cadena dada. Esto es muy sencillo si esas subcadenas son independientes entre sí. Pero ¿y si se organizan en forma "clave-valor"?. Por ejemplo, la siguiente cadena tiene la forma "jugador-deporte":

"Ronaldo=Futbol;Gasol=Baloncesto;Nadal=Tenis;Jordan=Baloncesto;"

Aquí tendríamos que tener en cuenta dos caracteres separadores: "=" y ";". Además, las subcademas habría que tratarlas teniendo en cuenta que las impares son nombres de deportistas y que las pares son nombres de deportistas. Lo mejor es que veamos un ejemplo:





El código



   import java.util.StringTokenizer;

   class PruebaST{

   static String entrada = "Ronaldo=Futbol;Gasol=Baloncesto;Nadal=Tenis;Jordan=Baloncesto;";

   public static void main(String args[]) {

   StringTokenizer st = new StringTokenizer(entrada, "=;");

   while(st.hasMoreTokens()) {

   String jugador = st.nextToken();

   String deporte = st.nextToken();

   System.out.println(jugador + " " + deporte);

   }

   }

   }





Resultado


La salida que daría ese código sería la siguiente:


   Ronaldo Futbol
   Gasol Baloncesto
   Nadal Tenis
   Jordan Baloncesto

52 comentarios:

  1. amigo se puede hacer eso pero no perder los espacios ni comas, etc, lo que en realidad quiero hacer es dividir todo el contenido y guardarlo en un arreglo, incluidas las comas, dos puntos, parentecis, etc. pero separar las palabras de esos caracteres.

    ResponderEliminar
  2. ya está solucionado solo tenía q agregar la opción true al constructor:

    StringTokenizer tokens = new StringTokenizer(linea, ":;()=><", true);

    ResponderEliminar
  3. Hola DrJekyll.

    No me ha dado tiempo a contestarte. Efectivamente, poniendo el returnDelims a true, también te devuelve los caracteres separadores:

    StringTokenizer(String str, String delim, boolean returnDelims)

    Saludos.

    ResponderEliminar
  4. hola nececito ordenar un temario
    esta asi
    1
    1.1
    1.1.1
    1.1.2 y asi pero cuando llega al 1.1.10
    me lo manda hasta debajo del 1.1
    ejemplo:
    1
    1.1
    1.1.10
    1.1.1
    1.1.2
    como le hago para que los ponga en orden
    es decir ue del 1.1.9
    siga el 1.1.10 y no me lo mande abajo del 1.1

    ResponderEliminar
  5. Hola.

    ¿Qué método estás utilizando para ordenar los temas? Pon el código que estás utilizando e intentaré ayudarte.

    Saludos.

    ResponderEliminar
  6. Solo estoy utilizando solamente este método que es el que genera el temario.


    private void generaTemario(AgregarContenidoTematicoForm form,
    HttpServletRequest request) {

    AgregarContenidoTematicoForm forma = (AgregarContenidoTematicoForm) form;
    Map temario = new TreeMap();

    if (request.getSession().getAttribute("Temario") != null) {
    temario = (Map) request.getSession().getAttribute("Temario");
    }

    NuevoModuloForm unidad = new NuevoModuloForm();

    if (Integer.valueOf(forma.getNivel()) == 1) {
    StringTokenizer tokenAux = new StringTokenizer(forma.getNumero(),
    "|");
    String numeroUnidadAux2 = tokenAux.nextToken();
    unidad.setCvePadre(numeroUnidadAux2);
    }
    if (Integer.valueOf(forma.getNivel()) == 2) {
    StringTokenizer tokenAux = new StringTokenizer(forma
    .getUnidadAprendizaje(), "|");
    String numeroUnidadAux2 = tokenAux.nextToken();
    unidad.setCvePadre(numeroUnidadAux2);
    }
    if (Integer.valueOf(forma.getNivel()) > 2) {
    StringTokenizer tokenAux = new StringTokenizer(forma
    .getResultadoAprendizaje(), "|");
    String numeroUnidadAux2 = tokenAux.nextToken();
    unidad.setCvePadre(numeroUnidadAux2);
    unidad.setCvePadre(forma.getResultadoAprendizaje());

    }
    unidad.setNombreUnidad(forma.getDescripcion());
    unidad.setNumeroUnidad(generaNumeroTema(forma, request) + "|");
    unidad.setNivel(forma.getNivel());
    unidad.setIndex(String.valueOf(temario.size()));
    unidad.setModulo(forma.getModulo());


    StringTokenizer tokenAux = new StringTokenizer(
    unidad.getNumeroUnidad(), "|");
    String numeroUnidadAux2 = tokenAux.nextToken();

    StringTokenizer token = new StringTokenizer(numeroUnidadAux2, "|");
    String numeroUnidadAux = token.nextToken();

    unidad.setNombreCompleto(numeroUnidadAux + "."
    + unidad.getNombreUnidad());
    unidad.setCveUnidad(forma.getUnidadAprendizaje());

    // unidad.setNumeroUnidadAux(String.valueOf(convierteNumero(unidad.getNumeroUnidad())));
    int numeroConvertido = convierteNumero(numeroUnidadAux
    + forma.getNivel());

    temario.put(numeroConvertido, unidad);

    request.getSession().setAttribute("Temario", temario);

    }

    ResponderEliminar
  7. por fa si alguien sabe como le puedo hacer digame me urge hacer eso porfa

    ResponderEliminar
  8. Buenas.

    Mi solución sería la siguiente:

    Partiría del argoritmo de ordenación por inserción:


    public static void insertSort (int[] v) {
    for (int i=1; i=0 && v[j]>aux; j--)
    v[j+1] = v[j];
    v[j+1] = aux;
    }
    }


    Siendo v un vector que contiene los números del temario. Y sustituiría v[j]>aux; por comparar(v[j],aux). Siendo "comparar" un método que fuese capaz de comparar la numeración de los temarios. Así:

    boolean b =comparar(num1,num2);

    devolvería true si num1 fuese mayor que num2
    devolvería false en caso contrario.

    Éste método compararía el primer número antes del punto de num1 con num2, si es mayor devolvería true. Si es menor, devolvería false. Si es igual, tendría que seguir comparando con el siguiente número del temario.


    Espero haberte ayudado.

    ResponderEliminar
  9. Otra alternativa, quizás más elegante, es implementar las interfaces Comparable y Comparador. Aquí tienes un ejemplo:

    https://sites.google.com/site/apuntesdejava/Home/comparator-y-comparable

    ResponderEliminar
  10. Lo que pasa esq estoy trabajando en web.Y los temas los inserto en orden.No entiendo porque en la pagina no me los muestra en el orden de como los fui insertando si ni siquiera tengo un metodo que los ordene. O ese ordenamiento lo hace por default?

    ResponderEliminar
  11. lo que pasa es que lo que quiero ordenar no es un vector, ni un arreglo o lista. Son datos que inserto en la pagina web, es decir inserto un nuevo tema y cuando le doy guardar me manda a otra pagina donde se van mostrando los temas que inserto.

    ResponderEliminar
  12. Buenas.

    Pero ¿datos de qué tipo? Supongo que serán String. ¿Cómo los insertas en la página?

    ResponderEliminar
  13. Los datos son de tipo String.
    Primero estoy en una pagina donde doy click en agregar nuevo tema.De ahi me aparece otra pagina donde lleno los campos del tema.Doy click en guardar y en ese momento se ejecuta el metodo "generar temario".Me regresa a la primer pagina y ahi es donde se van visualzando el tema que inserte.

    Pero los temas los inserto de uno en uno, es decir ingreso uno y lo guardo, ingreso otro y lo guardo y asi sucesivamente.

    ResponderEliminar
  14. Hola.

    Si no te importa, escríbeme a mi correo e intentaré ayudarte.

    Saludos.

    ResponderEliminar
  15. Hola, tengo un problema con este Tokenizer...
    Es la primera vez que lo utilizo y necesito separar tres variables que me salen juntas porque están en un método....

    (String idProducto,String nombreProducto, String descripcion)

    Como hago para separarlos¿???????

    ResponderEliminar
  16. Hola.

    Para separar las variables necesitarías un carácter separador. Si no, no hay forma de determinar donde acaba una y donde empieza otra. Muéstrame el código de ese método para que te pueda ayudar.

    Saludos.

    ResponderEliminar
  17. Muchas gracias me sirvio, saludos.

    ResponderEliminar
  18. ¿Como haria para hacer un programa que dada una cadena 12+14+3-8+5-4+1 haga toda esa operatoria. y la cadena siempre se le pueden agregar mas y mas numeros?

    ResponderEliminar
  19. Hola.

    No lo he probado, pero si tenemos los tokens separados por espacios, así: "8 + 3 - 5 + 4" , haría ésto:




    StringTokenizer st = new StringTokenizer(entrada, " ");

    int total = Integer.parseInt (st.nextToken());

    while(st.hasMoreTokens()) {

    operacion = st.nextToken();

    numero = Integer.parseInt(st.nextToken());

    if (operacion=="+")
    total = total + numero;

    if (operacion=="-")
    total = total - numero;

    }


    Espero que te sirva.

    Saludos.

    ResponderEliminar
  20. Hola tengo que hacer un parseo de un .txt Primero tengo que leerlo y dsp hacer el parceo

    ej: ponele que tengo asi en el txt

    Mariano , Rodriguez , 20
    Julian , Leguizamon, 30

    Me tiene que salir:

    Nombre:Mariano
    Apellido: Rodriguez
    Edad:20

    y asi con el otro nombre.

    Estoy perdido al momento de usas el tokenizer.

    Gracias

    ResponderEliminar
  21. Hola Kevin.

    Lo que tu pides sería algo así:


    class PruebaST{

    static String entrada; // Esta variable contiene la cadena de caracteres.

    public static void main(String args[]) {

    StringTokenizer st = new StringTokenizer(entrada, ",");

    while(st.hasMoreTokens()) {

    String nombre = st.nextToken();

    String apellido = st.nextToken();

    String edad = st.nextToken();



    }

    }

    }


    Para leer el archivo de texto desde la aplicación Java debes de utilizar

    FileReader. Puedes ver un ejemplo aquí: http://lineadecodigo.com/java/leer-fichero-de-texto-con-java/


    Saludos.

    ResponderEliminar
  22. Buen Dia

    SOy nuevo en Java y estoy corriendo el codigo expuesto...

    Al momento de correrlo me dice que no reconoce la variable val

    Gracias

    nelcelco

    ResponderEliminar
  23. Hola Nelcelco.

    Efectivamente, hay un error en el código que ya ha sido corregido. Hay que sustituir "val" por "deporte".

    Un saludo y gracias por comentar.

    ResponderEliminar
  24. Ches españoles weyes, el StringTokenizer ya no se debe usar, en lugar de eso usen split. Aquí les va la liga;

    http://docs.oracle.com/javase/1.4.2/docs/api/java/util/StringTokenizer.html

    ResponderEliminar
  25. Hola.

    Efectivamente, en la documentación se indica que:

    "StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead. "


    Traduzco:

    "StringTokenizer es una clase heredada que se mantiene por razones de compatibilidad, aunque su uso no se recomienda en el nuevo código. Se recomienda que cualquier persona que busque esta funcionalidad utilizar el método split de String o el paquete de java.util.regex lugar."


    O sea, que se recomienda utilizar split para nuevo código, pero StringTokenizer no está "deprecated" u obsoleto, por tanto, puede seguir usándose sin problemas. Conclusión: se pueden utilizar los dos, aunque se recomienda usar split.



    Saludos.

    ResponderEliminar
  26. alguien puede ayudarme con esta practica, lo que necesito es insertar una cadena donde el mismo numero de paréntesis que abre es el numero de paréntesis que sierra para que diga cadena valida, de lo contrario diga cadena no valida


    ((()))= cadena valida
    ((())= cadena no valida

    ResponderEliminar
  27. Hola.

    El código de lo que pides sería el siguiente:




     import java.util.StringTokenizer;

       class PruebaST{

       static String entrada = "(())";
      

       public static void main(String args[]) {

       StringTokenizer st = new StringTokenizer(entrada, ")",true);
       int i = st.countTokens();
      
       st = new StringTokenizer(entrada, "(",true);
       int j = st.countTokens();
      
       if(i==j)
           System.out.println("Cadena válida");
       else
           System.out.println("Cadena no válida");
      
       }

       }




    La clave de ésto es la inicialización del objeto StringTokenizer:

    StringTokenizer st = new StringTokenizer(entrada, ")",true);

    El último parámetro al estar puesto a true, hace que el carácter separador no solo sirve para separar, sino que también forme parte de la cadena. Ésto nos permitirá contar el número de carartéres "(" y ")".

    Espero que te haya servido.

    ResponderEliminar
  28. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  29. pero por ejemplo si tengo 23+20=0 no me separe el dos y el tres del numero 23

    ResponderEliminar
  30. Hola jose albertto.

    No se exactamente cual es tu pregunta, pero supongo que quieres separar los números de los signos de operación. En ese caso debes fijar como tokens dichos signos. Así:
     StringTokenizer st = new StringTokenizer(entrada, "+=");

    Saludos.

    ResponderEliminar
  31. Hola que tal.
    ¿Como puedo identificar el ultimo token de una cadena en código?

    ResponderEliminar
  32. Hola.

    Si estás utilizando el token ; se haría así:

    String ultimoToken = cadena.substring(cadena.lastIndexOf(";") + 1);


    Saludos.

    ResponderEliminar
  33. Amigos, buenas tardes, tengo una pregunta que no se ha mencionado,¿como puedo usar separadores que no sean caracteres , sino palabras : tarjeta aula av avenida ?

    Buenisimos los ejemplos ,escribo desde perú.

    ResponderEliminar
  34. Hola .

    Andrés: Te sugeriría que antes de tratar la cadena sustituyas "||" por "|". De esta forma obviarás los caracteres nulos y no tendrás el problema que mencionas. Puedes utilizar el método replace(char oldChar, char newChar) ..

    Anónimo: Puedes utilizar una palabra como separador, declarando esa palabra como separador, al igual que se declaran los caracteres.

    Saludos cordiales.

    ResponderEliminar
  35. Necesito hacer un programa en java que me separe palabras agudas graves esdrújulas y sobresdrújulas que me lea los acentos y las separaciones

    ResponderEliminar
  36. alguien podría ayudarme

    ResponderEliminar
  37. Hola.

    Desconozco si se puede hacer un programa para que separe palabras agudas esdrújulas y sobresdrújulas, ya que no existe un algoritmo que sea capaz determinar de qué tipo son.

    Para leer los acentos, puedes utilizar como token las vocales acentuadas, al igual que con las separaciones:
    StringTokenizer st = new StringTokenizer(entrada, "áéíóú ");

    Saludos cordiales.

    ResponderEliminar
  38. Hola, estoy haciendo un comienzo de analizador lexico peroblo que no me sale es que cuando pongas un texto junto con un token por ejemplo hola{ este se separe Me podrias ayudar?
    Nota: lo que se tiene que separar es lo dado por el usuario

    ResponderEliminar
  39. Hola.

    No he entendido muy bien tu pregunta, pero lo que parece que quieres hacer es exactamente lo que se consigue con stringtokenizer. Prueba con el ejemplo de este post u otro cualquiera que haga uso de stringtokenizer. Si tienes dudas, puedes preguntarme.

    Saludos.

    ResponderEliminar
  40. Saludos soy Alejandra, quisiera saber como comparo un token con una variable string para hacer determinado proceso?

    ResponderEliminar
  41. Hola Alejandra.

    Los tokens en este caso son de tipo String, así que puedes compararlos con tu variable como se comparan dos String. Puedes utilizar el método equals() .

    Saludos.

    ResponderEliminar
  42. como puedo hacer ingresada una cadena string por ejemplo
    "hola como estas" me despliegue "estas como hola" seria que el tokenizer enpiece desde el ultimo ?? eso no se de ante mano gracias

    ResponderEliminar
  43. Hola.
    Para hacer eso debes de utilizar un estructura de datos de tipo lifo (last in first out), es decir una pila (stack). Debes de insertar cada elemento (en este caso un string) mediante push. Luego los sacas mediante pop y saldrán en orden inverso al que entraron. Puedes ver un ejemplo aquí: http://www.javacoffeebreak.com/faq/faq0037.html .

    Saludos.

    ResponderEliminar
  44. Hola, Felipe mi nombre es María.

    Lo que yo necesito es hacer un código para poner una coma entre cada caracter. Por ejemplo: yo tengo varios archivos de texto con este formato:

    >AM406670.1 azoarcus sp. BH72, complete gameover
    QWERREWQWWERRREEWEQEWWEEWRERERWWEEWRRQEWEEWEQRRQRQRWEEWRQEEWEWRRWEQEWERWRWRWEWEWRWREREQRWRWEWERRWEQRWEQRWEQRQRQRRRRRRRRWQRQRQRQRQRQRQRQRQRQRQRRQRQRQRQRQRQRQRQRRQWRQRQRWRWRRQRWRWRWRRQRQRWRWRRWRWRRQRRWRWRQRQRWRRWRWRWRWRWRWRWRRQRWRWRWQRRQ

    Necesito hacer un solo archivo de texto quitando la primer linea de los archivos, poniendo una coma entre cada caracter, menos en el último. darle un número consecutivo a cada archivo, debe quedar así:
    1=Q,W,E,R,R,E,W,Q,W,W,E,R,R,R,E,E,W,E,Q,E,W,W,E,E,W,R,E,R,E,R,W,W,E,E,W,R,R,Q,E,W,E,E,W,E,Q,R,R,Q,R,Q,R,W,E,E,W,R,Q,E,E,W,E,W,R,R,W,E,Q,E,W,E,R,W,R,W,R,W,E,W,E,W,R,W,R,E,R,E,Q,R,W,R,W,E,W,E,R,Q,R
    2=Q,E,W,R,W,E,Q,W,E,Q,E,Q,E,R,W,R,W,E,Q,W,E,Q,E,Q,E,W,E,W,R,W,E,Q,W,E,Q,E,W,R,R,W,E,Q,E,Q,W,Q,W,Q,W,E,W,E,W,E,W,E,Q,R,R,Q,R,W,E,W,E,W,R,E,R,R,W,E,W,E,E,Q,E,Q,E,W,E,W,E,R,E,R,E,R,E,R,R,E,Q,E,Q,E,E,W,R,W
    3=Q,E,W,R,W,E,Q,E,E,W,R,Q,E,W,R,W,E,R,W,E,Q,R,R,W,E,E,Q,E,E,E,E,E,E,E,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,R,W,E,W,E,W,R,W,R,E,R,R,W,E,E,W,E,W,E,W,E,W,E,W,E,E,W,E,W,E,W,R,Q,E,W,E,W,R,R,R,R,W,R,W,R,W,R,W,R,E

    de todos los archivos debo hacer uno solo poniendo un numero, seguido del signo "=", separando cada letra por una coma solo el ultimo caracter de cada archivo no lleva la coma. y no tiene que haber espacios.

    ¿me podrás apoyar con esto?

    Saludos!

    ResponderEliminar
  45. Hola María.

    Para resolver lo que pides, yo lo haría en varios pasos:

    1. Leer archivo y guardar el contenido en una variable de tipo String (fuente del ejemplo geekytheory.com):

    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;

    public class LeerFichero {

    public static void muestraContenido(String archivo) throws FileNotFoundException, IOException {
    String cadena;
    FileReader f = new FileReader(archivo);
    BufferedReader b = new BufferedReader(f);
    while((cadena = b.readLine())!=null) {
    System.out.println(cadena);
    }
    b.close();
    }

    public static void main(String[] args) throws IOException {
    muestraContenido("/home/mario/archivo.txt");
    }

    }

    2. Convertir el String en un array de char:

    char[] charArray = cadena.toCharArray();

    3. Copiar el array de char a otro array de char intercalando el carácter ",":

    int j=0;
    for (int i=0; i<charArray.length; i++)
    nuevoArray[j]=charArray[i];
    j++;
    nuevoArray[j]=",";
    j++;
    }



    Esa sería la idea, si tienes alguna duda, pregúntame.

    Saludos.

    ResponderEliminar
  46. hola que tal, muy buen aporte de antemano gracias por compartirlo. Tengo duda en como separar esta cadena:
    frutasList.get(position - 1).getAlimento()+" = "+frutasList.get(position - 1).getCalorias()+" kcal"

    Esta me entrega jicama = 20 kcal, yo solo quieo obtener el 20 que son las calorias, como las declaro, espero puedas apoyarme

    ResponderEliminar
  47. Hola, como puedo hacer para que entre una palabra y una "," no se agregue un espacio. mi código es este:
    StringTokenizer token = new StringTokenizer(entrada,",", true);
    el resultado es este;
    sol , luna , estrella.
    y yo quiero que quede asi:
    sol, luna, estrella

    ResponderEliminar
  48. Hola.

    @Nancy Lopez: En tu caso los caracteres separadores serían "=" y "kcal". Pero hay un problema, stringtokenizer no permite utilizar separadores de más de un carácter y por tanto kcal no serviría como carácter separador. Tendrías que utilizar indexOf() y split(), para obtener la subcadena que tu necesitas. En el siguiente enlace se habla de este tema, si tienes alguna duda, dímelo:

    https://www.experts-exchange.com/questions/20080818/How-do-I-use-a-delimiter-with-multiple-characters-in-a-StringTokenizer.html

    @ALMA NEREIDA MOLINA SUAREZ: Puedes utilizar ésto: text.replace(" ,",",")


    Saludos.


    ResponderEliminar
  49. Buen dia, como hago para que los token se muestren en una sola linea. Los estos separando por comas, pero no quiero que se agregue salto de linea. Los muestra asi,
    alma,
    sol,
    luna,
    Y los quiero alma, sol, luna

    ResponderEliminar
  50. Que tal!

    Tengo un archivo con esta estructura:



    No Autorizacion : 201556621075315
    Fecha Autorizacion : 2015-12-30
    Tipo Documento : FACE
    Estado Documento : ORIGINAL
    Serie : FCA
    Rango Autorizado : 25001 50000
    Numero de Factura : 39703
    Fecha Emision : 2017-08-07

    Razon social : BRENNTAG GUATEMALA, S.A.
    NIT : 1048643
    Pais : GT
    Municipio : GUAT
    Lenguaje : ES
    Departamento : GUATEMALA
    Calle : 23 AVENIDA 40-19 ZONA 12
    Personalizado 01 :
    Personalizado 02 :
    Personalizado 03 :
    Personalizado 04 :
    Personalizado 05 :
    Personalizado 06 :

    Razon Social : LAPCO (GUATEMALA), SOCIEDAD ANONIMA
    NIT : 60319577
    Mail : vilmaruiz@gruposolid.com

    mi separador de tokens sería dos puntos (:), pero como lo recorro y seteo cada valor en una variable distinta o varios valores en una sola? De antemano gracias

    Saludos @Felipe

    ResponderEliminar
  51. mi correo es kenpachi2783@gmail.com por si me logras ayudar

    Saludos

    ResponderEliminar
  52. @Alma Molina: Entiendo que estás utilizando System.out.println para mostrar el resultado por pantalla. Si no quieres que haga un salto de línea, utiliza System.out.print .

    Saludos.

    ResponderEliminar