令牌化错误:java.util.regex.PatternSyntaxException,悬而未决的元字符“*”

我使用split()来标记用*分隔的string,格式如下:

 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”中的exceptionjava.util.regex.PatternSyntaxException:在索引0附近悬挂元字符'*'

我的猜测是,在原始文本文件的年龄之后缺less*是造成这种情况的原因。 我如何解决它?

不,问题是*是正则expression式中的保留字符,所以您需要将其转义。

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

*表示“零或多个以前的expression式”(请参阅Pattern Javadocs ),并且您没有给它以前的expression式,使您的分割expression式非法。 这就是为什么这个错误是PatternSyntaxException

我有类似的问题与regex = "?" 。 在正则expression式中,所有特殊字符都有一些意义。 所以你需要有"\\"作为你的正则expression式的前缀。

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

第一个答案涵盖了它。

我猜测你可能会决定将你的信息存储在不同的类/结构中。 在这种情况下,你可能不希望结果从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. } 

然后,您最初发布的parsing代码的版本将如下所示:(这将它们存储在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(); }
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(); } 

这是因为*被用作元字符来表示前一个字符的一个或多个出现。 所以,如果我写M *,那么它会寻找文件MMMMMM …..! 这里你使用*作为唯一的字符,所以编译器正在寻找字符来查找多个事件,所以它会抛出exception。