Ошибка Tokenizing: java.util.regex.PatternSyntaxException, оборванный метасимвол ‘*’
Я использую split()
для tokenize строки, разделенной *
следующим образом:
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(); }
И я получаю это исключение:
- Как использовать stringstream для разделения разделенных запятыми строк
- Токенизация строк в C
- Шаблоны C ++ Угловые скобки Pitfall - Что такое C ++ 11?
- Как читать ввод по-символам в Java?
- Сканер против StringTokenizer против String.Split
Исключение в streamе «main» java.util.regex.PatternSyntaxException: Висячий метасимвол «*» рядом с индексом 0 *
Я предполагаю, что отсутствие *
после возраста в исходном текстовом файле вызывает это. Как мне обойти это?
- Разделение разделенной запятой строки в PL / SQL хранимой процедуре
- Как получить токен из Lucene TokenStream?
- Вложенная функция функции strtok в C
- Как сделать токенизацию строки в C ++?
- Преобразование разделенной запятой строки в массив в PL / SQL
- Каков самый простой / лучший / самый правильный способ перебора символов строки в Java?
- Есть ли функция для разделения строки в PL / SQL?
- Тонирование и сортировка с помощью XSLT 1.0
Нет, проблема в том, что *
является зарезервированным символом в регулярных выражениях, поэтому вам нужно его избежать.
String [] separado = line.split("\\*");
*
означает «ноль или более предыдущего выражения» (см. Pattern
Javadocs ), и вы не давали ему никакого предыдущего выражения, что делает ваше разделенное выражение незаконным. Вот почему ошибка была PatternSyntaxException
.
У меня была аналогичная проблема с regex = "?"
, Это происходит для всех специальных символов, которые имеют некоторое значение в регулярном выражении. Поэтому вам нужно иметь "\\"
в качестве префикса для вашего регулярного выражения.
String [] separado = line.split("\\*");
Первый ответ охватывает его.
Я предполагаю, что где-то вниз по линии вы можете решить сохранить свою информацию в другом classе / структуре. В этом случае вы, вероятно, не захотите, чтобы результаты попадали в массив из метода split ().
Вы не просили об этом, но мне скучно, так что вот пример, надеюсь, что это полезно.
Это может быть class, который вы пишете, чтобы представлять одного человека:
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. }
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
list = new LinkedList (); 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(); } try { String ruta="entrada.al"; BufferedReader reader = new BufferedReader(new FileReader(ruta)); LinkedList
list = new LinkedList (); 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(); }
Это потому, что * используется как метасимвол, чтобы обозначать одно или несколько случаев предыдущего символа. Так что, если я напишу M *, тогда он будет искать файлы MMMMMM …..! Здесь вы используете * в качестве единственного символа, поэтому компилятор ищет персонажа для поиска нескольких вхождений, поэтому он генерирует исключение. 🙂