上个月写那段处理CVS文件中的逗号的小程序时,顺便写了个测试程序。测试程序先读一“|”分割字段的文件。我们原来的程序中,都是使用Java中的 StringTokenizer 类来处理读入的每行数据。我的测试程序中改用String.split()方法,但是处理一“|”分割字段的文件总是不正确。换成其它分隔符或者使用StringTokenizer就没问题。墨迹了好长时间也没找出问题。
“大事不决问Google,内事不决问老婆”。老婆是指望不上了,她是做会计工作的。只好问Google。随便看了一篇文章,还没看完,就明白是怎么回事了:把正则表达式当字符串用了。
先来看一下class StringTokenizer constructor:Constructs a string tokenizer for the specified string.
StringTokenizer(String str, String delim)
第一个String是要处理的字符串,第二个String是字符串中使用的分隔符。如果省略第二个参数,缺省的分隔符是空格。创建一个StringTokenizer对象,然后使用它的hasMoreTokens()和nextToken()方法来获得分隔好的字段。
再来看一下class String 中的split方法:Splits this string around matches of the given regular expression.
public String[] split(String regex)
这个方法比StringTokenizer要方便一些,分隔后的字段直接存到一个String数组中。只要把分隔符当做参数传给这个方法就行了。
但是,split方法需要的不是一个普通的字符串,它需要一个正则表达式作为参数。在我的程序中,我直接使用string.split(“|”),想使用“|”作为分隔符。正巧,“|”是正则表达式中的元字符,它是有特殊含义的:它是一个或表达式。如果你只是想找“|”,就必须使用“\”取消它的特殊含义。在正则表达式中,你必须写成“\|”。但是当你把这样一个正则表达式传给split方法时,这个方法又不认了,因为“\”在Java string 中是有特殊含义的,你必须再使用一个"\"来转义。所以最后传给split的参数是“\\|”。
什么叫祸不单行啊。还没高兴一会儿,又被正则表达式绊倒了。
我需要一个用字符串替换字符串的方法,在API中找了一下,还真找着了:
public String replaceAll(String regex, String replacement)
这个方法可以:Replaces each substring of this string that matches the given regular expression with the given replacement.
但是,不好用啊,什么都没替换掉。郁闷半天,发现自己在同一个地方又跌倒了一回。replaceAll方法参数需要的也是正则表达式。
在Java使用正则表达式,因为Java也有转义字符("\"),会使得一些表达是看上去很奇怪。比如,要在正则表达式中表示一个字符"\",必须在这个字符前面再加个"\",因为"\"是元字符,必须使用转义字符"\"来取消它的特殊含义。这样,在正则表达式中就会出现两个"\"。到了Java那里,又需要使用Java的转义字符"\"来转义,于是每个"\"前面再加一个“\",这样就变成了4个"\"。麻烦吧。
(这是一篇老博文,11-1-31 下午4:18 发布在Google Blogger上。但我只是几年前在那里发了几篇文章,早已经不维护了,干脆把看得上眼的文章搬过来算了)