Java读取文件及基于正则表达式的获取电话号码功能详解
作者:chaoyu168 发布时间:2022-06-18 09:11:45
本文实例讲述了Java读取文件及基于正则表达式的获取电话号码功能。分享给大家供大家参考,具体如下:
1、正则表达式
正则表达式,又称 正规表示法 、 常规表示法 (英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
用到的一些特殊构造正则表达式的意 * 析:
? | 当该字符 紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的 贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。 |
.点 | 匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符,请使用像“[\s\S]”的模式。 |
(pattern) | 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“”。 |
(?:pattern) | 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。 |
(?=pattern) | 正向肯定 预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例 如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配 “Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从 包含预查的字符之后开始。 |
(?!pattern) | 正向否定 预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如 “Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中 的“Windows”。 |
(?<=pattern) | 反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。 |
(?<!pattern) | 反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!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、手机号码
组成
国家区域号-手机号码
手机号码格式比较固定,无非是13x xxxx xxxx或者15x xxxx xxxx再或者18x xxxx xxxx的格式。座机就比较麻烦,比如长途区号变长(3位或者4位)电话号码变长(7位或者8位)有些还需要输入分机号。
通常可以看到解决这个复杂问题的解决方案是手机号和座机号分开。座机号拆分成三段,区号,电话号码+分机号。但是为了表单看起来清爽,设计的时候给了一个“万能”的输入框,给用户输入电话号码或者手机号码。
在这样的一个需求的大前提下,用复杂的正则表达式解决验证的问题是一种快速的解决方案。
首先搞定最容易的手机号码
因为目前开放的号段是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());
}
只是手机号码可以匹配可以给出下面的匹配正则表达式:
(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+\\d{8})
当我们 加上国家区域号 (86)或者(+86)或者86-或者直接是86,可以使用下面的正则表达式:
"(?:(\\(\\+?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、座机号码
组成:
国家区域号(+86等)-区号-固定电话号码-分机号
三位 区号 的部分
010, 021-029,852(香港)
因为采用三位区号的地方都是8位电话号码,因此可以写成
(010|021|022|023|024|025|026|027|028|029|852)\d{8}
当然不会这么简单,有些人习惯(010) xxxxxxxx的格式,我们也要支持一把,把以上表达式升级成
再看4位区号的城市
这里简单判断了不可能存在0111或者0222的区号,以及电话号码是7位或者8位。
最后是分机号(1-4位的数字)
(?<分机号>\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、编码实现
实现功能:读取文件,将其中的电话号码存入一个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
{
/**
* 获得电话号码的正则表达式:包括固定电话和移动电话
* 符合规则的号码:
* 1》、移动电话
* 86+‘-'+11位电话号码
* 86+11位正常的电话号码
* 11位正常电话号码a
* (+86) + 11位电话号码
* (86) + 11位电话号码
* 2》、固定电话
* 区号 + ‘-' + 固定电话 + ‘-' + 分机号
* 区号 + ‘-' + 固定电话
* 区号 + 固定电话
* @return 电话号码的正则表达式
*/
public static String isPhoneRegexp()
{
String regexp = "";
//能满足最长匹配,但无法完成国家区域号和电话号码之间有空格的情况
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);
//固定电话正则表达式
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)
{
//获得固定电话和移动电话的正则表达式
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);
}
}
②、读取文件并调用电话号码获取
实现方式:根据文件路径获得文件后,一行行读取,去获取里面的电话号码
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("读取文件内容出错");
e.printStackTrace();
}
return phoneSet;
}
}
③、测试
public static void main(String argv[])
{
String filePath = "F:\\three.txt";
Set<String> phoneSet = getPhoneNumFromFile(filePath);
System.out.println("电话集合:" + phoneSet);
}
文件中数据:
结果:
电话集合:[86132221, (86)13222144332, 86-13222144332, 32434343, (+86)13222144332, 13888888888]
PS:这里再为大家提供2款非常方便的正则表达式工具供大家参考使用:
JavaScript正则表达式在线测试工具:
http://tools.jb51.net/regex/javascript
正则表达式在线生成工具:
http://tools.jb51.net/regex/create_reg
希望本文所述对大家java程序设计有所帮助。
来源:http://blog.csdn.net/chaoyu168/article/details/51861095


猜你喜欢
- 时区的概念与转换首先要知道时区之间的转换关系,其实这很简单:把当地时间减去当地时区,剩下的就是格林威治时间了。 例如北京时间的18:00就是
- 介绍RANGE分区基于一个给定的连续区间范围,早期版本RANGE主要是基于整数的分区。在5.7版本中DATE、DATETIME列也可以使用R
- 附上代码与运行结果截图:import time# 获取当前时间now = time.localtime()# 格式化日期now_ = tim
- python 利用pywifi模块实现连接网络破解wifi密码实时监控网络,具体内容如下:import pywififrom pywifi
- 1.自定义浏览器窗口大小或全屏from selenium import webdriverimport timedriver = webdr
- 把中文字符转换回Unicode字符。见下列代码:<%function unicode(str)dim i,j,c,
- 本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下import requestsimport bs4im
- 使用SQL对数据进行提取和分析时,我们经常会遇到数据重复的场景,需要我们对数据进行去重后分析。以某电商公司的销售报表为例,常见的去重方法我们
- 一提起Google的产品,大多数人可能都会想到用一个词来形容,“简洁”。简单得来又实用,这就是Google的产品设计方针了。Jon Wile
- 目录一、梳理功能二、准备数据库三、构造和数据库相关的实体类书籍用户NormalUser类四、封装数据库相关操作数据库链接操作针对书籍表操作针
- 本文实例为大家分享了python批量转换图片为黑白的具体代码,供大家参考,具体内容如下用到的库:OpenCV、osimport cv2imp
- 将数组传递给前台模板:1.def modifyBtn(req,modifyip): print modifyip c
- 本文实例讲述了Python安装Flask环境及简单应用。分享给大家供大家参考,具体如下:安装环境使用虚拟环境安装Flask,可以避免包的混乱
- 在Python中,类表示具有相同属性和方法的对象的集合。在使用类时,需要先定义类,然后再创建类的实例,通过类的实例就可以访问类中的属性和方法
- 一、解决方案1.1 描述接口context-path后端的两个接口服务请求前缀,如下:前缀1: /bryant前缀2: /1.2 vue.c
- datetime64与unix时间戳互转在用pandas处理数据时,经常要处理一些时间类型数据,经常把pandas时间类型与datetime
- 指定变量类型有时您可能需要为变量指定类型,这可以通过 casting 来完成,Python 是一门面向对象的语言,因此它使用类来定义数据类型
- 一、安装openpyxl模块Python操作excel主要用到了openpyxl模块,按win+R打开cmd,在里面输入pip3 insta
- 在对excel的操作中,调整列的顺序以及添加一些列也是经常用到的,下面我们用pandas实现这一功能。1、调整列的顺序>>>
- PyQt5简介1.什么是GUI:Graphical User Interface,图形用户界面,用于人机交互。2.怎么设计GUI:Qt3.什