本文實(shí)例講述了Java讀取文件及基于正則表達(dá)式的獲取電話號(hào)碼功能。分享給大家供大家參考,具體如下:
1、正則表達(dá)式
正則表達(dá)式,又稱 正規(guī)表示法 、 常規(guī)表示法 (英語(yǔ):Regular Expression,在代碼中常簡(jiǎn)寫(xiě)為regex、regexp或RE),計(jì)算機(jī)科學(xué)的一個(gè)概念。正則表達(dá)式使用單個(gè)字符串來(lái)描述、匹配一系列符合某個(gè)句法規(guī)則的字符串。在很多文本編輯器里,正則表達(dá)式通常被用來(lái)檢索、替換那些符合某個(gè)模式的文本。
用到的一些特殊構(gòu)造正則表達(dá)式的意義解析:
?
|
當(dāng)該字符 緊跟在任何一個(gè)其他限制符(*,+,?,{n},{n,},{n,m})后面時(shí),匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認(rèn)的 貪婪模式則盡可能多的匹配所搜索的字符串。例如,對(duì)于字符串“oooo”,“o+?”將匹配單個(gè)“o”,而“o+”將匹配所有“o”。 |
.點(diǎn)
|
匹配除“\r\n”之外的任何單個(gè)字符。要匹配包括“\r\n”在內(nèi)的任何字符,請(qǐng)使用像“[\s\S]”的模式。 |
(pattern)
|
匹配pattern并獲取這一匹配。所獲取的匹配可以從產(chǎn)生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號(hào)字符,請(qǐng)使用“ |
(?:pattern)
|
匹配pattern但不獲取匹配結(jié)果,也就是說(shuō)這是一個(gè)非獲取匹配,不進(jìn)行存儲(chǔ)供以后使用。這在使用或字符“(|)”來(lái)組合一個(gè)模式的各個(gè)部分是很有用。例如“industr(?:y|ies)”就是一個(gè)比“industry|industries”更簡(jiǎn)略的表達(dá)式。 |
(?=pattern)
|
正向肯定 預(yù)查,在任何匹配pattern的字符串開(kāi)始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說(shuō),該匹配不需要獲取供以后使用。例 如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配 “Windows3.1”中的“Windows”。預(yù)查不消耗字符,也就是說(shuō),在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開(kāi)始下一次匹配的搜索,而不是從 包含預(yù)查的字符之后開(kāi)始。 |
(?!pattern)
|
正向否定 預(yù)查,在任何不匹配pattern的字符串開(kāi)始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說(shuō),該匹配不需要獲取供以后使用。例如 “Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中 的“Windows”。 |
(?<=pattern)
|
反向肯定預(yù)查,與正向肯定預(yù)查類似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。 |
(?<!pattern)
|
反向否定預(yù)查,與正向否定預(yù)查類似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。 |
量詞使用
X { n }? | X ,恰好 n 次 |
X { n ,}? | X ,至少 n 次 |
X { n , m}? | X ,至少 n 次,但是不超過(guò) m 次 |
2、手機(jī)號(hào)碼
組成
國(guó)家區(qū)域號(hào)-手機(jī)號(hào)碼
手機(jī)號(hào)碼格式比較固定,無(wú)非是13x xxxx xxxx或者15x xxxx xxxx再或者18x xxxx xxxx的格式。座機(jī)就比較麻煩,比如長(zhǎng)途區(qū)號(hào)變長(zhǎng)(3位或者4位)電話號(hào)碼變長(zhǎng)(7位或者8位)有些還需要輸入分機(jī)號(hào)。
通常可以看到解決這個(gè)復(fù)雜問(wèn)題的解決方案是手機(jī)號(hào)和座機(jī)號(hào)分開(kāi)。座機(jī)號(hào)拆分成三段,區(qū)號(hào),電話號(hào)碼+分機(jī)號(hào)。但是為了表單看起來(lái)清爽,設(shè)計(jì)的時(shí)候給了一個(gè)“萬(wàn)能”的輸入框,給用戶輸入電話號(hào)碼或者手機(jī)號(hào)碼。
在這樣的一個(gè)需求的大前提下,用復(fù)雜的正則表達(dá)式解決驗(yàn)證的問(wèn)題是一種快速的解決方案。
首先搞定最容易的手機(jī)號(hào)碼
因?yàn)槟壳伴_(kāi)放的號(hào)段是130-139, 150-159, 185-189, 180
只考慮移動(dòng)電話(手機(jī))號(hào)碼的可以使用下面方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public static void main(String[] args) { String text = "13522158842;托爾斯泰;test2;13000002222;8613111113313" ; Pattern pattern = Pattern.compile( "(?<!\\d)(?:(?:1[358]\\d{9})|(?:861[358]\\d{9}))(?!\\d)" ); Matcher matcher = pattern.matcher(text); StringBuffer bf = new StringBuffer( 64 ); while (matcher.find()) { bf.append(matcher.group()).append( "," ); } int len = bf.length(); if (len > 0 ) { bf.deleteCharAt(len - 1 ); } System.out.println(bf.toString()); } |
只是手機(jī)號(hào)碼可以匹配可以給出下面的匹配正則表達(dá)式:
(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})
當(dāng)我們 加上國(guó)家區(qū)域號(hào) (86)或者(+86)或者86-或者直接是86,可以使用下面的正則表達(dá)式:
"(?:(\\(\\+?86\\))((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})|" +
"(?:86-?((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})|" +
"(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})"
注意 :為了最長(zhǎng)得匹配電話號(hào)碼,需要寫(xiě)成三句,并且相對(duì)長(zhǎng)的需要放在前面,否則匹配到了之后,后面的就不會(huì)匹配了。
3、座機(jī)號(hào)碼
組成:
國(guó)家區(qū)域號(hào)(+86等)-區(qū)號(hào)-固定電話號(hào)碼-分機(jī)號(hào)
三位 區(qū)號(hào) 的部分
010, 021-029,852(香港)
因?yàn)椴捎萌粎^(qū)號(hào)的地方都是8位電話號(hào)碼,因此可以寫(xiě)成
(010|021|022|023|024|025|026|027|028|029|852)\d{8}
當(dāng)然不會(huì)這么簡(jiǎn)單,有些人習(xí)慣(010) xxxxxxxx的格式,我們也要支持一把,把以上表達(dá)式升級(jí)成
再看4位區(qū)號(hào)的城市
這里簡(jiǎn)單判斷了不可能存在0111或者0222的區(qū)號(hào),以及電話號(hào)碼是7位或者8位。
最后是分機(jī)號(hào)(1-4位的數(shù)字)
(?<分機(jī)號(hào)>\D?\d{1,4})?
以上拼裝起來(lái)就是:
"(?:(\\(\\+?86\\))(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)|" +
"(?:(86-?)?(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)"
4、編碼實(shí)現(xiàn)
實(shí)現(xiàn)功能:讀取文件,將其中的電話號(hào)碼存入一個(gè)Set返回。
方法介紹:
find()
:嘗試查找與該模式匹配的輸入序列的下一個(gè)子序列。
group()
:返回由以前匹配操作所匹配的輸入子序列。
①、從一個(gè)字符串中獲取出其中的電話號(hào)碼
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 從字符串中截取出電話號(hào)碼 * @author zcr * */ public class CheckIfIsPhoneNumber { /** * 獲得電話號(hào)碼的正則表達(dá)式:包括固定電話和移動(dòng)電話 * 符合規(guī)則的號(hào)碼: * 1》、移動(dòng)電話 * 86+‘-'+11位電話號(hào)碼 * 86+11位正常的電話號(hào)碼 * 11位正常電話號(hào)碼a * (+86) + 11位電話號(hào)碼 * (86) + 11位電話號(hào)碼 * 2》、固定電話 * 區(qū)號(hào) + ‘-' + 固定電話 + ‘-' + 分機(jī)號(hào) * 區(qū)號(hào) + ‘-' + 固定電話 * 區(qū)號(hào) + 固定電話 * @return 電話號(hào)碼的正則表達(dá)式 */ public static String isPhoneRegexp() { String regexp = "" ; //能滿足最長(zhǎng)匹配,但無(wú)法完成國(guó)家區(qū)域號(hào)和電話號(hào)碼之間有空格的情況 String mobilePhoneRegexp = "(?:(\\(\\+?86\\))((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})|" + "(?:86-?((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})|" + "(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})" ; // System.out.println("regexp = " + mobilePhoneRegexp); //固定電話正則表達(dá)式 String landlinePhoneRegexp = "(?:(\\(\\+?86\\))(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)|" + "(?:(86-?)?(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)" ; regexp += "(?:" + mobilePhoneRegexp + "|" + landlinePhoneRegexp + ")" ; return regexp; } /** * 從dataStr中獲取出所有的電話號(hào)碼(固話和移動(dòng)電話),將其放入Set * @param dataStr 待查找的字符串 * @param phoneSet dataStr中的電話號(hào)碼 */ public static void getPhoneNumFromStrIntoSet(String dataStr,Set<String> phoneSet) { //獲得固定電話和移動(dòng)電話的正則表達(dá)式 String regexp = isPhoneRegexp(); System.out.println( "Regexp = " + regexp); Pattern pattern = Pattern.compile(regexp); Matcher matcher = pattern.matcher(dataStr); //找與該模式匹配的輸入序列的下一個(gè)子序列 while (matcher.find()) { //獲取到之前查找到的字符串,并將其添加入set中 phoneSet.add(matcher.group()); } //System.out.println(phoneSet); } } |
②、讀取文件并調(diào)用電話號(hào)碼獲取
實(shí)現(xiàn)方式:根據(jù)文件路徑獲得文件后,一行行讀取,去獲取里面的電話號(hào)碼
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * 讀取文件操作 * * @author zcr * */ public class ImportFile { /** * 讀取文件,將文件中的電話號(hào)碼讀取出來(lái),保存在Set中。 * @param filePath 文件的絕對(duì)路徑 * @return 文件中包含的電話號(hào)碼 */ public static Set<String> getPhoneNumFromFile(String filePath) { Set<String> phoneSet = new HashSet<String>(); try { String encoding = "UTF-8" ; File file = new File(filePath); if (file.isFile() && file.exists()) { // 判斷文件是否存在 InputStreamReader read = new InputStreamReader( new FileInputStream(file), encoding); // 考慮到編碼格 BufferedReader bufferedReader = new BufferedReader(read); String lineTxt = null ; while ((lineTxt = bufferedReader.readLine()) != null ) { //讀取文件中的一行,將其中的電話號(hào)碼添加到phoneSet中 CheckIfIsPhoneNumber.getPhoneNumFromStrIntoSet(lineTxt, phoneSet); } read.close(); } else { System.out.println( "找不到指定的文件" ); } } catch (Exception e) { System.out.println( "讀取文件內(nèi)容出錯(cuò)" ); e.printStackTrace(); } return phoneSet; } } |
③、測(cè)試
1
2
3
4
5
6
|
public static void main(String argv[]) { String filePath = "F:\\three.txt" ; Set<String> phoneSet = getPhoneNumFromFile(filePath); System.out.println( "電話集合:" + phoneSet); } |
文件中數(shù)據(jù):
結(jié)果:
電話集合:[86132221, (86)13222144332, 86-13222144332, 32434343, (+86)13222144332, 13888888888]
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
原文鏈接:http://blog.csdn.net/chaoyu168/article/details/51861095