Ошибка токенизации: java.util.regex.PatternSyntaxException, висячий метасимвол '*' - PullRequest
51 голосов
/ 28 мая 2009

Я использую split() для токенизации строки, разделенной * в следующем формате:

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

Я читаю это из файла с именем "entrada.al", используя этот код:

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();
    }

И я получаю это исключение:

Исключение в потоке "main" java.util.regex.PatternSyntaxException: висячий метасимвол '*' около индекса 0 *

Я предполагаю, что отсутствие * после возраста в исходном текстовом файле является причиной этого. Как мне обойти это?

Ответы [ 4 ]

136 голосов
/ 28 мая 2009

Нет, проблема в том, что * является зарезервированным символом в регулярных выражениях, поэтому вам нужно его экранировать.

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

* означает «ноль или более предыдущего выражения» (см. Pattern Javadocs ), и вы не давали ему никакого предыдущего выражения, что делало ваше выражение split недопустимым. Вот почему ошибка была PatternSyntaxException.

6 голосов
/ 26 мая 2014

У меня была похожая проблема с regex = "?". Это происходит для всех специальных символов, которые имеют некоторое значение в регулярном выражении. Таким образом, вы должны иметь "\\" в качестве префикса к своему регулярному выражению.

String [] separado = line.split("\\*");
3 голосов
/ 28 мая 2009

Первый ответ охватывает это.

Я предполагаю, что где-то внизу вы можете решить сохранить вашу информацию в другом классе / структуре. В этом случае вы, вероятно, не захотите, чтобы результаты передавались в массив из метода split ().

Вы не просили об этом, но мне скучно, так что вот пример, надеюсь, это полезно.

Это может быть класс, который вы пишете для представления одного человека:


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.
} 

Тогда версия кода синтаксического анализа, которую вы первоначально разместили, будет выглядеть примерно так: (Это сохраняет их в LinkedList, вы можете использовать что-то еще, например, Hashtable и т. Д.)


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();
}

2 голосов
/ 05 сентября 2011

Это потому, что * используется как метасимвол для обозначения одного или нескольких вхождений предыдущего символа. Так что, если я напишу M *, он будет искать файлы MMMMMM .....! Здесь вы используете * в качестве единственного символа, поэтому компилятор ищет символ, чтобы найти несколько вхождений, поэтому он вызывает исключение

...