令牌化错误:java.util.regex.PatternSyntaxException,悬挂的元字符’*’

Tokenizing Error: java.util.regex.PatternSyntaxException, dangling metacharacter '*'

我正在使用split()来标记化以下格式的用*分隔的字符串:

1
2
3
4
5
name*lastName*ID*school*age
%
name*lastName*ID*school*age
%
name*lastName*ID*school*age

我正在使用以下代码从名为" entrada.al"的文件中读取此信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
    }

我得到这个异常:

Exception in thread"main" java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 0
*

我的猜测是,原始文本文件上缺少老化后的*会导致这种情况。 我该如何解决?


不,问题在于*是正则表达式中的保留字符,因此您需要对其进行转义。

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

*表示"零个或多个先前的表达式"(请参见Pattern Javadocs),并且您没有给它任何先前的表达式,因此拆分表达式是非法的。这就是为什么错误是PatternSyntaxException的原因。


我对regex ="?"有类似的问题。对于在正则表达式中具有某些含义的所有特殊字符,都会发生这种情况。因此,您需要以"\\"作为正则表达式的前缀。

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


这是因为*被用作元字符来表示一个或多个先前字符的出现。因此,如果我写M *,那么它将查找文件MMMMMM .....!在这里,您使用*作为唯一字符,因此编译器正在寻找该字符以查找多次出现的字符,因此它将引发异常。


第一个答案涵盖了它。

我猜想您可能决定将您的信息存储在不同的类/结构中。在那种情况下,您可能不希望结果从split()方法进入数组。

您没有要求,但是我很无聊,所以这里有个例子,希望对您有所帮助。

这可能是您编写的代表一个人的课程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<wyn>
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.
}
</wyn>

然后,您最初发布的解析代码的版本将如下所示:
(这会将它们存储在LinkedList中,您可以使用其他东西,例如Hashtable等。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<wyn>
try
{
    String ruta="entrada.al";
    BufferedReader reader = new BufferedReader(new FileReader(ruta));

    LinkedListPerson> list = new LinkedListPerson>();

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