字符串分离
按设定的条件分离字符串是分离命令、读取文本文件的数据等常见操作。 以后,在文本文件中保存以下数据的情况下,在读入文件后,String的split ) )可以帮助各行的数据分离。
jzdhs 64/5/26 0939002302 5433343
momor 68/7/23 0939100391 5432343
示例6.8是一个简单的演示,假设fakeFileData中的数据是读取到文件中的文本数据。
例6.8 SplitStringDemo.java
公共类剥离字符串演示{
publicstaticvoidmain (string args [ ] ) {
String[] fakeFileData={
' JZ DHS/t64/5/26/t 0939002302/t 5433343 ',
' momor/t68/7/23/t 0939100391/t 5432343 ' };
for (字符串数据: fake filedata ) {
string[]tokens=data.split((/t );
for(stringtoken:tokens )
system.out.print(Token'/t|' );
}
System.out.println (;
}
}
}
执行结果:
JZ DHS|64/5/26|0939002302|5433343 |
momor|68/7/23|0939100391|5432343 |
split ) )是split ) )方法的使用。 其中,根据设置的分隔符设置,将字符串分成几个子字符串,并在字符串数组中返回。 使用过Java的人可能会想到java.util.StringTokenizer,但基本上,API文件显示StringTokenizer已经是“遗产类”(Legacy Class ) 的理由是,为了与旧版本的Java程序兼容,在创建新的Java程序时不推荐使用。 相反,使用split ()会是一个好方案。 此外,还可以将其与正则表达式结合使用进行字符串分离。
使用正则表达式(Regular Expression ) )。
如果查看J2SE 1.4或更高版本的String联机API文档的说明,可以找到matches ()、replaceAll () )等方法,参数是正则表达式(Regular Expression )字符串。 正则表达式由数学家Stephen Kleene于1956年提出,主要用于字符串格式比对,后广泛用于信息领域,现已成为国际标准化组织(ISO )的标准之一。
从J2SE 1.4开始,Java支持正则表达式。 有关支持的正则表达式的信息位于API文件的java.util.regex.Pattern类中,可以将正则表达式应用于字符串匹配、替换和分离等操作。 下面是一些简单的正则表达式。
1到9、a到z等简单字符归类可以使用预定义的符号。
表6-4列出了一些常用的字符匹配符号。
表6-4字符核对符号
水平。
与任意字符一致
/d
与0~9中的任意一个数字一致
/D
适用于0~9以外的文字
/s
与/t、/n、/x0B、/f、/r等空白字符一致
/w
属于a~z、a~z、0~9等文字,也就是数字或字母
/W
相当于a~z、a~z、0~9等以外的文字。 也就是说,除了数字和字母以外都是适用的
例如,如果有字符串abcdebcadxbc,则在归类中使用. bc时,匹配的子字符串为三个: abc、ebc和xbc。使用cd时,匹配的子字符串只有abcd。
例6.9证实了这个说明。
例6.9 RegularExpressionDemo.java
publicclassregularexpressiondemo {
publicstaticvoidmain (字符串[ ] args ) {
String text='abcdebcadxbc ';
string[]tokens=text.split('.BC );
for(stringtoken:tokens ) {
system.out.print(Token ' );
}
System.out.println (;
tokens=text.split('.CD ' );
for(stringtoken:tokens ) {
system.out.print(Token ' );
}
System.out.println();
}
}
执行结果:
d ad
ebcadxbc
使用.bc来作比对,由于符合的子字符串有abc、ebc、xbc 3个,所以split()方法会使用这3个字符串为依据来作字符串分离,返回的自然就是不符合表达式.bc的d与ad。同理如果表达式为..cd,则使用split()返回的就是不符合..cd的ebcadxbc。
也可以使用字符类(Character Class)来比较一组字符范围。
表6-5示范了几个字符类的设定方式。
表6-5 字符类范例
[abc]
符合a、b或c
[^abc]
符合a或b或c之外的字符
[a-zA-Z]
符合a~z或者是A~Z的字符
[a-d[m-p]]
a~d或者是m~p,也可以写成[a-dm-p]
[a-z&&[def]]
a~z并且是d或e或f,结果就是d或e或f可以符合
[a-z&&[^bc]]
a~z并且不是b或c
[a-z&&[^m-p]]
a~z并且不是m~p
指定一个字符之外,也可以加上“贪婪量词”(Greedy Quantifiers)来指定字符可能出现的次数。表6-6示范了几个例子。
表6-6 贪婪量词范例
X?
X可出现一次或完全没有
X*
X可出现零次或多次
X+
X可出现一次或多次
X{n}
X可出现n次
X{n,}
X可出现至少n次
X{n, m}
X可出现至少n次,但不超过m次
另外,还有Reluctant quantifiers、Possessive quantifiers等的指定,可以自行参考java.util.regex.Pattern类API文件中的说明。
在String类中,matches()方法可以让您验证字符串是否符合指定的正则表达式,这通常用于验证使用者输入的字符串数据是否正确,例如电话号码格式;replaceAll()方法可以将符合正则表达式的子字符串置换为指定的字符串;split()方法可以让您依指定的正则表达式,将符合的子字符串排除,剩下的子字符串分离出来并以字符串数组返回。范例6.9已经示范了split()方法的使用,接下来在范例6.10中示范replaceAll()与matches()方法的运用。
范例6.10 UseRegularExpression.java
import java.io.*;
public class UseRegularExpression {
public static void main(String args[])
throws IOException {
BufferedReader reader =
new BufferedReader(
new InputStreamReader(System.in));
System.out.println("abcdefgabcabc".replaceAll(".bc", "###"));
String phoneEL = "[0-9]{4}-[0-9]{6}";
String urlEL = "";
String emailEL = "^[_a-z0-9-]+(.[_a-z0-9-]+)*" +
"@[a-z0-9-]+([.][a-z0-9-]+)*$";
System.out.print("输入手机号码: ");
String input = reader.readLine();
if(input.matches(phoneEL))
System.out.println("格式正确");
else
System.out.println("格式错误");
System.out.print("输入href标签: ");
input = reader.readLine();
// 验证href标签
if(input.matches(urlEL))
System.out.println("格式正确");
else
System.out.println("格式错误");
System.out.print("输入电子邮件: ");
input = reader.readLine();
// 验证电子邮件格式
if(input.matches(emailEL))
System.out.println("格式正确");
else
System.out.println("格式错误");
}
}
执行结果:
###defg######
输入手机号码: 0939-100391
格式正确
输入href标签:
格式正确
输入电子邮件: caterpillar.onlyfun@gmail.com
格式正确
Pattern和Matcher
String上可使用正则表达式的操作,实际上是利用了java.util.regex.Pattern与java.util.regex.Matcher的功能。当调用String的matches()方法时,实际上是调用Pattern的静态方法matches(),这个方法会返回boolean值,表示字符串是否符合正则表达式。
如果想要将正则表达式视为一个对象来重复使用,可以使用Pattern的静态方法compile()进行编译。compile()方法会返回一个Pattern的实例,这个实例代表正则表达式,之后就可以重复使用Pattern实例的matcher()方法来返回一个Matcher的实例,代表符合正则式的实例,这个实例上有一些寻找符合正则式条件的方法可供操作。范例6.11作了示范。
范例6.11 UsePatternMatcher.java
import java.util.regex.*;
public class UsePatternMatcher {
public static void main(String[] args) {
String phones1 =
"jydxl 的手机号码:0939-100391/n" +
"momor 的手机号码:0939-666888/n";
Pattern pattern = Pattern.compile(".*0939-//d{6}");
Matcher matcher = pattern.matcher(phones1);
while(matcher.find()) {
System.out.println(matcher.group());
}
String phones2 =
"caterpillar 的手机号码:0952-600391/n" +
"bush 的手机号码:0939-550391";
matcher = pattern.matcher(phones2);
while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
范例6.11会寻找手机号码为0939开头的号码,假设号码来源不止一个(如phones1、phones2),则可以编译好正则表达式并返回一个Pattern对象,之后就可以重复使用这个Pattern对象,在比对时使用matcher()返回符合条件的Matcher实例。find()方法表示是否有符合的字符串,group()方法则可以将符合的字符串返回。程序的执行结果如下:
jydxl 的手机号码:0939-100391
momor 的手机号码:0939-666888
bush 的手机号码:0939-550391
下面使用Pattern与Matcher改写范例6.9,让程序可以返回符合正则式的字符串,而不是返回不符合的字符串。
范例6.12 RegularExpressionDemo2.java
import java.util.regex.*;
public class RegularExpressionDemo2 {
public static void main(String[] args) {
String text = "abcdebcadxbc";
Pattern pattern = Pattern.compile(".bc");
Matcher matcher = pattern.matcher(text);
while(matcher.find()) {
System.out.println(matcher.group());
}
System.out.println();
}
}
执行结果:
abc
ebc
xbc