Ошибка 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();
}
И я получаю это исключение:
Исключение в потоке "main" java.util.regex.PatternSyntaxException: Висячий метасимвол '*' рядом с индексом 0 *
Я предполагаю, что причиной этого является отсутствие *
после возраста в исходном текстовом файле. Как мне обойти это?
Ответы
Ответ 1
Нет, проблема в том, что *
является зарезервированным символом в регулярных выражениях, поэтому вам нужно его избежать.
String [] separado = line.split("\\*");
*
означает "ноль или более предыдущего выражения" (см. Pattern
Javadocs), и вы не давали это любое предыдущее выражение, делающее ваше разделенное выражение незаконным. Вот почему ошибка была PatternSyntaxException
.
Ответ 2
У меня была аналогичная проблема с regex = "?"
. Это происходит для всех специальных символов, которые имеют некоторое значение в регулярном выражении. Поэтому вам нужно иметь "\\"
в качестве префикса для вашего регулярного выражения.
String [] separado = line.split("\\*");
Ответ 3
Первый ответ охватывает его.
Я предполагаю, что где-то по линии вы можете решить сохранить свою информацию в другом классе/структуре. В этом случае вы, вероятно, не захотите, чтобы результаты попадали в массив из метода 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();
}
Ответ 4
Это потому, что * используется как метасимвол, чтобы обозначить одно или несколько случаев предыдущего символа. Так что, если я напишу M *, тогда он будет искать файлы MMMMMM.....! Здесь вы используете * в качестве единственного символа, поэтому компилятор ищет символ для поиска нескольких вхождений, поэтому он генерирует исключение.:)