IPV6

import java.util.Objects;
public class Ipv6 implements Comparable<Ipv6>{
    private Long first;
    private Long second;

    public Ipv6(Long left, Long right) {
        this.first = left;
        this.second = right;
    }
    public Long getFirst() {
        return first;
    }
    public void setFirst(Long left) {
        this.first = left;
    }
    public Long getSecond() {
        return second;
    }
    public void setSecond(Long right) {
        this.second = right;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Ipv6)) return false;
        Ipv6 that = (Ipv6) o;
        return Objects.equals(first, that.first) &&
                Objects.equals(second, that.second);
    }
    @Override
    public int hashCode() {
        return Objects.hash(first, second);
    }
    @Override
    public int compareTo(Ipv6 o) {
        if(first.equals(o.first)){
            return second.compareTo(o.second);
        }else {
            return first.compareTo(o.first);
        }
    }
}


import org.apache.commons.lang.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Ipv6Test {
    public static void main(String[] args) throws Exception {
//        System.out.println("2001::".split("::").length);
        test(toIpv6StandardFormat("2001::1234"));

//        System.out.println(Long.toHexString((-1L << 10)));
//        Long start = System.currentTimeMillis();
//        String[] ips4Test = new String[]{"FFFF:1111:FFFF:2222:1245:BA98:3210:4562",
//                "FFFF:0:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", "7654:0:FFFF:7654:562:222:7622:0", "0:0:0:0:0:0:0:0"};
//        for (String testCase : ips4Test) {
//            test(testCase);
//        }
//        System.out.println(System.currentTimeMillis() - start);
    }

    private static void test(String testCase) throws Exception {
        Ipv6 ipv6 = ipv6ToLongs(testCase);
        String ipString = longsToIpv6(ipv6);
        boolean eq = testCase.equalsIgnoreCase(ipString);
        System.out.println("本次测试 ipv6 地址: " + testCase
                + ", 再转回 ipv6 字符串: " + ipString + ", 是否与原字符串相等: " + eq);
        System.out.println("网络位: " + longsToIpv6(getIpv6NetworkPart(testCase, 46)));
        if (!eq) {
            throw new IllegalStateException("本次测试未通过!testCase: " + testCase);
        }
    }

    /**
     * 将 IPv6 地址转为 两个long ,只支持冒分十六进制表示法
     */
    public static Ipv6 ipv6ToLongs(String ipString) {
        if (ipString == null || ipString.isEmpty()) {
            throw new IllegalArgumentException("ipString cannot be null.");
        }
        String[] ipSlices = ipString.split(":");
        if (ipSlices.length != 8) {
            throw new IllegalArgumentException(ipString + " is not an ipv6 address.");
        }
        long[] ipv6 = new long[2];
        for (int i = 0; i < 8; i++) {
            int index = i >> 2;
            String slice = ipSlices[i];
            // 以 16 进制解析
            long num = Long.parseLong(slice, 16);
            // 每组 16 位
            // 每个 long 保存四组,i >> 2 = i / 4
            ipv6[index] = ipv6[index] << 16;
            ipv6[index] = ipv6[index] | num;
            // a|=b的意思就是把a和b按位或然后赋值给a 按位或的意思就是先把a和b都换成2进制,然后用或操作,相当于a=a|b
        }
        return new Ipv6(ipv6[0], ipv6[1]);
    }

    public static String longsToIpv6(Ipv6 ipv6) {
        StringBuilder sb = new StringBuilder(32);
        Long[] numbers = new Long[]{ipv6.getFirst(), ipv6.getSecond()};
        for (int i = numbers.length - 1; i >= 0; i--) {
            // 每个 long 保存四组
            long numSlice = numbers[i];
            for (int j = 0; j < 4; j++) {
                // 取最后 16 位
                long current = numSlice & 0xFFFF;
                sb.insert(0, ":" + Long.toString(current, 16));
                // 右移 16 位,去除掉已经处理过的 16 位
                numSlice >>= 16;
            }
        }
        // 去掉第一个的 :
        return sb.substring(1, sb.length());
    }


    public static boolean isIpv6(String ip) {
        String pattern = "^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(ip);
        if (m.find()) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isContainIpv6(String str) {
        String pattern = "\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(str);
        if (m.find()) {
            return true;
        } else {
            return false;
        }
    }

    public static Ipv6 getIpv6NetworkPart(String ipv6, int mask) throws Exception {
        Ipv6 ipv6Before = ipv6ToLongs(ipv6);
        //如果子网掩码<=64位,则网络位在第一个long,直接将第二个long置为0
        if (mask <= 64) {
            ipv6Before.setSecond(0L);
            ipv6Before.setFirst(ipv6Before.getFirst() & (-1L << (64 - mask)));
        } else {//如果子网掩码>64位,则网络位有落到第二个long,第一个long不变
            int leave = mask - 64;
            ipv6Before.setSecond(ipv6Before.getSecond() & ((-1L << (64 - leave))));
        }
        return ipv6Before;
    }

    //转化为ipv6标准格式
    public static String toIpv6StandardFormat(String str) throws Exception{
        if(str.equals("::")){
            return "0:0:0:0:0:0:0:0";
        }
        //处理以:: 结尾格式
        if(str.endsWith("::")){
            str = str+" ";
        }
        String[] ipPart = str.split("::");
        if(ipPart.length > 2){
            throw new Exception("not ipv6");
        }
        StringBuilder sb = new StringBuilder();
        if (ipPart.length == 1) {
           if(str.split(":").length == 8){
               return str;
           }else {
               throw new Exception("not ipv6");
           }
        } else {
            if(StringUtils.isBlank(ipPart[0])){
                int tempLen = ipPart[1].split(":").length;
                for(int i=1; i<= 8-tempLen; i++){
                    sb.append("0:");
                }
                sb.append(ipPart[1]);
            }else if(StringUtils.isBlank(ipPart[1])){
                int tempLen = ipPart[0].split(":").length;
                sb.append(ipPart[0]);
                for(int i=1; i<= 8-tempLen; i++){
                    sb.append(":0");
                }
            }else {
                int len = 8 - ipPart[0].split(":").length - ipPart[1].split(":").length;
                sb.append(ipPart[0]);
                for(int i=1; i<= len; i++){
                    sb.append(":0");
                }
                sb.append(":"+ipPart[1]);
            }
            return sb.toString();
        }
    }
}
上一篇:Python实战:常用正则表达式汇总


下一篇:【蜕变之路】第46天 字符串校验与SQL查询(2019年10月26日)