• 技术文章 >Java >java教程

    Java读取文件以及获取电话号码功能(基于正则表达式)的详解

    黄舟黄舟2017-09-06 14:16:57原创1243

    这篇文章主要介绍了Java读取文件及基于正则表达式的获取电话号码功能,结合实例形式详细分析了正则匹配操作的相关语法及电话号码匹配的原理与实现技巧,需要的朋友可以参考下

    本文实例讲述了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]

    以上就是Java读取文件以及获取电话号码功能(基于正则表达式)的详解的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:Java 获取 以及
    上一篇:Java实现图片上传功能的简单示例 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • Java中Map集合体系的基本使用和常用API• Java数据结构常见排序算法(总结分享)• 一起来分析java设计模式之单例• 深入分析Java的序列化与反序列化• Java知识点总结之多线程基础
    1/1

    PHP中文网