web-dev-qa-db-fra.com

Erreur de tokenisation: Java.util.regex.PatternSyntaxException, balancement du métacaractère '*'

J'utilise split() pour symboliser une chaîne séparée par * suivant ce format:

name*lastName*ID*school*age
%
name*lastName*ID*school*age
%
name*lastName*ID*school*age

Je lis ceci à partir d'un fichier nommé "entrada.al" en utilisant ce code:

static void leer() {

    try {
        String ruta="entrada.al";
        File myFile = new File (ruta);
        FileReader fileReader = new FileReader(myFile);

        BufferedReader reader = new BufferedReader(fileReader);

        String line = null;

        while ((line=reader.readLine())!=null){
            if (!(line.equals("%"))){
                String [] separado = line.split("*"); //SPLIT CALL
                names.add(separado[0]);
                lastNames.add(separado[1]);
                ids.add(separado[2]);
                ages.add(separado[3]);
            }
        }

        reader.close();
    }

Et je reçois cette exception:

Exception dans le thread "principal" Java.util.regex.PatternSyntaxException: balancement du méta-caractère '*' près de l'index 0 *

Je suppose que le manque d'un * après l'âge sur le fichier texte d'origine est à l'origine de ce problème. Comment le contourner?

52
andandandand

Non, le problème est que * est un caractère réservé dans les expressions rationnelles, vous devez donc y échapper.

String [] separado = line.split("\\*");

* signifie "zéro ou plus de l'expression précédente" (voir Pattern Javadocs ), et vous ne lui donniez aucune expression précédente, rendant votre expression fractionnée illégale. C'est pourquoi l'erreur était un PatternSyntaxException .

142
Michael Myers

J'ai eu un problème similaire avec regex = "?". Cela se produit pour tous les caractères spéciaux qui ont une signification dans une expression régulière. Vous devez donc avoir "\\" comme préfixe de votre expression régulière.

String [] separado = line.split("\\*");
6
Aniket Thakur

La première réponse le couvre.

Je suppose que quelque part sur la ligne, vous pouvez décider de stocker vos informations dans une classe/structure différente. Dans ce cas, vous ne voudriez probablement pas que les résultats entrent dans un tableau à partir de la méthode split ().

Vous ne l'avez pas demandé, mais je m'ennuie, alors voici un exemple, j'espère que c'est utile.

Ce pourrait être la classe que vous écrivez pour représenter une seule personne:


class Person {
            public String firstName;
            public String lastName;
            public int id;
            public int age;

      public Person(String firstName, String lastName, int id, int age) {
         this.firstName = firstName;
         this.lastName = lastName;
         this.id = id;
         this.age = age;
      }  
      // Add 'get' and 'set' method if you want to make the attributes private rather than public.
} 

Ensuite, la version du code d'analyse que vous avez initialement publiée ressemblerait à ceci: (Cela les stocke dans une LinkedList, vous pouvez utiliser autre chose comme une Hashtable, etc.)


try 
{
    String ruta="entrada.al";
    BufferedReader reader = new BufferedReader(new FileReader(ruta));

    LinkedList<Person> list = new LinkedList<Person>();

    String line = null;         
    while ((line=reader.readLine())!=null)
    {
        if (!(line.equals("%")))
        {
            StringTokenizer st = new StringTokenizer(line, "*");
            if (st.countTokens() == 4)          
                list.add(new Person(st.nextToken(), st.nextToken(), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken)));         
            else            
                // whatever you want to do to account for an invalid entry
                  // in your file. (not 4 '*' delimiters on a line). Or you
                  // could write the 'if' clause differently to account for it          
        }
    }
    reader.close();
}
3
jdc0589

C'est parce que * est utilisé comme métacaractère pour signifier une ou plusieurs occurrences du caractère précédent. Donc, si j'écris M *, il recherchera les fichiers MMMMMM .....! Ici, vous utilisez * comme seul caractère afin que le compilateur recherche le caractère pour trouver plusieurs occurrences de, donc il lève l'exception. :)

2
Vishal Joshi