Java讀取文件及基于正則表達(dá)式的獲取電話號碼功能詳解
本文實例講述了Java讀取文件及基于正則表達(dá)式的獲取電話號碼功能。分享給大家供大家參考,具體如下:
1、正則表達(dá)式
正則表達(dá)式,又稱 正規(guī)表示法 、 常規(guī)表示法 (英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學(xué)的一個概念。正則表達(dá)式使用單個字符串來描述、匹配一系列符合某個句法規(guī)則的字符串。在很多文本編輯器里,正則表達(dá)式通常被用來檢索、替換那些符合某個模式的文本。
用到的一些特殊構(gòu)造正則表達(dá)式的意義解析:
|
?
|
當(dāng)該字符 緊跟在任何一個其他限制符(*,+,?,{n},{n,},{n,m})后面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認(rèn)的 貪婪模式則盡可能多的匹配所搜索的字符串。例如,對于字符串“oooo”,“o+?”將匹配單個“o”,而“o+”將匹配所有“o”。 |
|
.點
|
匹配除“\r\n”之外的任何單個字符。要匹配包括“\r\n”在內(nèi)的任何字符,請使用像“[\s\S]”的模式。 |
|
(pattern)
|
匹配pattern并獲取這一匹配。所獲取的匹配可以從產(chǎn)生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號字符,請使用“ |
|
(?:pattern)
|
匹配pattern但不獲取匹配結(jié)果,也就是說這是一個非獲取匹配,不進(jìn)行存儲供以后使用。這在使用或字符“(|)”來組合一個模式的各個部分是很有用。例如“industr(?:y|ies)”就是一個比“industry|industries”更簡略的表達(dá)式。 |
|
(?=pattern)
|
正向肯定 預(yù)查,在任何匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例 如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配 “Windows3.1”中的“Windows”。預(yù)查不消耗字符,也就是說,在一個匹配發(fā)生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從 包含預(yù)查的字符之后開始。 |
|
(?!pattern)
|
正向否定 預(yù)查,在任何不匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如 “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 次,但是不超過 m 次 |
2、手機號碼
組成
國家區(qū)域號-手機號碼
手機號碼格式比較固定,無非是13x xxxx xxxx或者15x xxxx xxxx再或者18x xxxx xxxx的格式。座機就比較麻煩,比如長途區(qū)號變長(3位或者4位)電話號碼變長(7位或者8位)有些還需要輸入分機號。
通常可以看到解決這個復(fù)雜問題的解決方案是手機號和座機號分開。座機號拆分成三段,區(qū)號,電話號碼+分機號。但是為了表單看起來清爽,設(shè)計的時候給了一個“萬能”的輸入框,給用戶輸入電話號碼或者手機號碼。
在這樣的一個需求的大前提下,用復(fù)雜的正則表達(dá)式解決驗證的問題是一種快速的解決方案。
首先搞定最容易的手機號碼
因為目前開放的號段是130-139, 150-159, 185-189, 180
只考慮移動電話(手機)號碼的可以使用下面方法
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());
}
只是手機號碼可以匹配可以給出下面的匹配正則表達(dá)式:
(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})
當(dāng)我們 加上國家區(qū)域號 (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})"
注意 :為了最長得匹配電話號碼,需要寫成三句,并且相對長的需要放在前面,否則匹配到了之后,后面的就不會匹配了。
3、座機號碼
組成:
國家區(qū)域號(+86等)-區(qū)號-固定電話號碼-分機號
三位 區(qū)號 的部分
010, 021-029,852(香港)
因為采用三位區(qū)號的地方都是8位電話號碼,因此可以寫成
(010|021|022|023|024|025|026|027|028|029|852)\d{8}
當(dāng)然不會這么簡單,有些人習(xí)慣(010) xxxxxxxx的格式,我們也要支持一把,把以上表達(dá)式升級成
再看4位區(qū)號的城市
這里簡單判斷了不可能存在0111或者0222的區(qū)號,以及電話號碼是7位或者8位。
最后是分機號(1-4位的數(shù)字)
(?<分機號>\D?\d{1,4})?
以上拼裝起來就是:
"(?:(\\(\\+?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、編碼實現(xiàn)
實現(xiàn)功能:讀取文件,將其中的電話號碼存入一個Set返回。
方法介紹:
find():嘗試查找與該模式匹配的輸入序列的下一個子序列。
group():返回由以前匹配操作所匹配的輸入子序列。
①、從一個字符串中獲取出其中的電話號碼
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 從字符串中截取出電話號碼
* @author zcr
*
*/
public class CheckIfIsPhoneNumber
{
/**
* 獲得電話號碼的正則表達(dá)式:包括固定電話和移動電話
* 符合規(guī)則的號碼:
* 1》、移動電話
* 86+‘-'+11位電話號碼
* 86+11位正常的電話號碼
* 11位正常電話號碼a
* (+86) + 11位電話號碼
* (86) + 11位電話號碼
* 2》、固定電話
* 區(qū)號 + ‘-' + 固定電話 + ‘-' + 分機號
* 區(qū)號 + ‘-' + 固定電話
* 區(qū)號 + 固定電話
* @return 電話號碼的正則表達(dá)式
*/
public static String isPhoneRegexp()
{
String regexp = "";
//能滿足最長匹配,但無法完成國家區(qū)域號和電話號碼之間有空格的情況
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中獲取出所有的電話號碼(固話和移動電話),將其放入Set
* @param dataStr 待查找的字符串
* @param phoneSet dataStr中的電話號碼
*/
public static void getPhoneNumFromStrIntoSet(String dataStr,Set<String> phoneSet)
{
//獲得固定電話和移動電話的正則表達(dá)式
String regexp = isPhoneRegexp();
System.out.println("Regexp = " + regexp);
Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(dataStr);
//找與該模式匹配的輸入序列的下一個子序列
while (matcher.find())
{
//獲取到之前查找到的字符串,并將其添加入set中
phoneSet.add(matcher.group());
}
//System.out.println(phoneSet);
}
}
②、讀取文件并調(diào)用電話號碼獲取
實現(xiàn)方式:根據(jù)文件路徑獲得文件后,一行行讀取,去獲取里面的電話號碼
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
{
/**
* 讀取文件,將文件中的電話號碼讀取出來,保存在Set中。
* @param filePath 文件的絕對路徑
* @return 文件中包含的電話號碼
*/
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)
{
//讀取文件中的一行,將其中的電話號碼添加到phoneSet中
CheckIfIsPhoneNumber.getPhoneNumFromStrIntoSet(lineTxt, phoneSet);
}
read.close();
}
else
{
System.out.println("找不到指定的文件");
}
}
catch (Exception e)
{
System.out.println("讀取文件內(nèi)容出錯");
e.printStackTrace();
}
return phoneSet;
}
}
③、測試
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]
PS:這里再為大家提供2款非常方便的正則表達(dá)式工具供大家參考使用:
JavaScript正則表達(dá)式在線測試工具:
http://tools.jb51.net/regex/javascript
正則表達(dá)式在線生成工具:
http://tools.jb51.net/regex/create_reg
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java正則表達(dá)式技巧大全》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
相關(guān)文章
Spring Boot項目使用Flyway的詳細(xì)教程
這篇文章主要介紹了Spring Boot項目使用Flyway,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07
將BigDecimal轉(zhuǎn)成字符串為科學(xué)計數(shù)法的踩坑記錄
這篇文章主要介紹了將BigDecimal轉(zhuǎn)成字符串為科學(xué)計數(shù)法的踩坑記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
Spring?boot詳解fastjson過濾字段為null值如何解決
這篇文章主要介紹了解決Spring?boot中fastjson過濾字段為null值的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07

