1、Java数据类型

1、基本数据类型的变量:

/**
 * 1、基本数据类型的变量:
 *
 *   1)、整数类型:byte(1字节=8bit),short(2字节),int(4字节),long(8字节)
 *
 *   2)、浮点数类型:float(4字节),double(8字节)
 *
 *   3)、字符类型:char(2字节)----Unicode码
 *
 *   4)、布尔类型:boolean(未指定字节数)----true和false
 *
 * 2、引用数据类型的变量:
 *
 *   除了基本类型(primitive type)和枚举类型(enumeration type),剩下的都是引用类型,比如String。
 * */

(1)、Demo01: 数据取值范围的注意:

//静态方法不需要实例化
    public static void basicDataDemo(){
        /**
         * 1、声明long型变量,必须以"l"或"L"结尾,其整数默认是int类型(易超出其取值范围而报错)
         * 2、需注意数据的取值范围
         *      (1)、byte的取值范围:-128~127(-2^7~2^7-1)
         *      (2)、short的取值范围:-32768 ~ 32767(-2^15~2^15-1)
         *      (3)、int取值范围:-2147483648 ~ 2147483647(-2^31~2^31-1)
         *      (4)、。。。。。。
         * 3、浮点型默认是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型会造成精度损失,因此需要强制类型转换
         * 4、整数默认是int类型
         */
        //错误:
        //long l = 2147483648;
        long l = 2147483648L;

        //byte b=128;
        byte b=28;

        //丢失精度,两种解决方案
        //float f=1.2;
        float f1=1.2f;
        float f2=(float) 1.2;

        //丢失精度
        //short s1 = 1;
        //s1 = s1 + 1;
        short s1 = 1;
        short s2 = 1;
        s1 = (short)(s1 + 1);
        //有隐含的强制类型转换,推荐使用
        s2 +=1;

        System.out.println(l);  //2147483648
        System.out.println(b);  //28
        System.out.println(f1); //1.2
        System.out.println(f2); //1.2
        System.out.println(s1); //2
        System.out.println(s2); //2
    }

(2)、Demo02: String引用数据类型的注意:


/**
* JVM的基本了解:
* 1、方法区内存:存储字节码代码片段、静态变量
* 2、堆内存:new实例变量、数组
* 3、栈内存:局部变量
* */

//静态方法不需要实例化
    public static void stringDataDemo(){
        /**
         * 1、String s1 = "123";
         *  在静态区的“123”(字符串常量池)创建了一个对象
         * 2、String s2 = new String("123");
         *  创建了二个对象:一个在静态区的“123”(字符串常量池)对象,一个是用new创建在堆上的对象
         * */
        String s1 = "123";
        String s2 = new String("123");
        System.out.println(s1 == s2);   //false

        String s3 = "123456";
        String s4 = "123" + "456";
        System.out.println(s3 == s4);   //true

        String s5 = s1 + "456";
        System.out.println(s5 == s4);   //false

        /**
         * String与Stringbuffer/ Stringbulider的区别:
         * 
         * String类型是只读字符串,字符串内容不允许改变
         * Stringbuffer/ Stringbulider表示字符串对象可以修改
         * 1、 Stringbuffer:有synchronized关键字修饰,表示线程安全的,效率低
         * 2、 Stringbulider:无synchronized关键字修饰,表示非线程安全的,效率高
         * 开发建议使用:Stringbuffer》Stringbulider》String
         * */
        String a = new String("123");
        StringBuffer b = new StringBuffer("123");
        b.append("456");    //字符串a不允许修改
        System.out.println("a:"+ a);    //a:123
        System.out.println("b:"+ b);    //b:123456
    }


2、包装类:

/**
 * 包装类:
 * 1、基本包装类
 *    Boolean
 *    Byte
 *    Short
 *    Character
 *    Long
 *    Integer
 *    Float
 *    Double
 *
 * 2、高精度数字
 *    BigDecimal
 *    BigInteger
 * */

(1)、Demo03: 数据间转换的注意:

/**
 * 1、自动类型转换
 *    byte 、char 、short --> int --> long --> float --> double
 *
 * 2、强制类型转换
 *    使用强转符:(),可能导致精度损失
 * */

//静态方法不需要实例化
    public static void dataConversionDemo(){
        /**
         * 数据转换工具类:DataConversionUtil
         * 1、自动装箱:自动将基本数据类型转换为包装器类型
         * 2、自动拆箱:自动将包装器类型转换为基本数据类型
         * 3、声明包装类可以避免空指针异常
         * */
        String a ="123";
        int b;
        int c;
        //利用包装类实现自动装箱与自动拆箱,即数据类型转换
        b = Integer.parseInt(a);
        //调用工具类的静态方法
        c = DataConversionUtil.toInt(a);
        System.out.println(b);  //123
        System.out.println(c);  //123
        
        int d =123;
        String e ;
        String f ;
        e = DataConversionUtil.toStr(d);
        f = String.valueOf(d);
        System.out.println(e);  //123
        System.out.println(f);  //123

        //避免空指针异常
        Integer i = null;
        System.out.println(i);  //null
        //报错
        //int j = null;
        //System.out.println(j);
    }

(2)、数据转换工具类:

DataConversionUtil.class

1)、转换为数组:

   /**
     * 转换为Integer数组<br>
     *
     * @param str 被转换的值
     * @return 结果
     */
    public static Integer[] toIntArray(String str) {
        return toIntArray(",", str);
    }

    /**
     * 转换为Long数组<br>
     *
     * @param str 被转换的值
     * @return 结果
     */
    public static Long[] toLongArray(String str) {
        return toLongArray(",", str);
    }

    /**
     * 转换为Integer数组<br>
     *
     * @param split 分隔符
     * @param split 被转换的值
     * @return 结果
     */
    public static Integer[] toIntArray(String split, String str) {
        if (StringUtils.isEmpty(str)) {
            return new Integer[]{};
        }
        String[] arr = str.split(split);
        final Integer[] ints = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++) {
            final Integer v = toInt(arr[i], 0);
            ints[i] = v;
        }
        return ints;
    }

    /**
     * 转换为Long数组<br>
     *
     * @param split 分隔符
     * @param str   被转换的值
     * @return 结果
     */
    public static Long[] toLongArray(String split, String str) {
        if (StringUtils.isEmpty(str)) {
            return new Long[]{};
        }
        String[] arr = str.split(split);
        final Long[] longs = new Long[arr.length];
        for (int i = 0; i < arr.length; i++) {
            final Long v = toLong(arr[i], null);
            longs[i] = v;
        }
        return longs;
    }

    /**
     * 转换为String数组<br>
     *
     * @param str 被转换的值
     * @return 结果
     */
    public static String[] toStrArray(String str) {
        return toStrArray(",", str);
    }

    /**
     * 转换为String数组<br>
     *
     * @param split 分隔符
     * @param split 被转换的值
     * @return 结果
     */
    public static String[] toStrArray(String split, String str) {
        return str.split(split);
    }

2)、转换为Enum对象:

 

  /**
     * 转换为Enum对象<br>
     * 如果给定的值为空,或者转换失败,返回默认值<br>
     *
     * @param clazz        Enum的Class
     * @param value        值
     * @param defaultValue 默认值
     * @return Enum
     */
    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (clazz.isAssignableFrom(value.getClass())) {
            @SuppressWarnings("unchecked")
            E myE = (E) value;
            return myE;
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr)) {
            return defaultValue;
        }
        try {
            return Enum.valueOf(clazz, valueStr);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 转换为Enum对象<br>
     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     *
     * @param clazz Enum的Class
     * @param value 值
     * @return Enum
     */
    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value) {
        return toEnum(clazz, value, null);
    }

 

3)、转换为BigInteger:

 

  /**
     * 转换为BigInteger<br>
     * 如果给定的值为空,或者转换失败,返回默认值<br>
     * 转换失败不会报错
     *
     * @param value        被转换的值
     * @param defaultValue 转换错误时的默认值
     * @return 结果
     */
    public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (value instanceof BigInteger) {
            return (BigInteger) value;
        }
        if (value instanceof Long) {
            return BigInteger.valueOf((Long) value);
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr)) {
            return defaultValue;
        }
        try {
            return new BigInteger(valueStr);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 转换为BigInteger<br>
     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * 转换失败不会报错
     *
     * @param value 被转换的值
     * @return 结果
     */
    public static BigInteger toBigInteger(Object value) {
        return toBigInteger(value, null);
    }

 

4)、转换为BigDecimal:

 

  /**
     * 转换为BigDecimal<br>
     * 如果给定的值为空,或者转换失败,返回默认值<br>
     * 转换失败不会报错
     *
     * @param value        被转换的值
     * @param defaultValue 转换错误时的默认值
     * @return 结果
     */
    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        if (value instanceof Long) {
            return new BigDecimal((Long) value);
        }
        if (value instanceof Double) {
            return new BigDecimal((Double) value);
        }
        if (value instanceof Integer) {
            return new BigDecimal((Integer) value);
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr)) {
            return defaultValue;
        }
        try {
            return new BigDecimal(valueStr);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 转换为BigDecimal<br>
     * 如果给定的值为空,或者转换失败,返回默认值<br>
     * 转换失败不会报错
     *
     * @param value 被转换的值
     * @return 结果
     */
    public static BigDecimal toBigDecimal(Object value) {
        return toBigDecimal(value, null);
    }

 

5)、全角半角转换:

  /**
     * 半角转全角
     *
     * @param input String.
     * @return 全角字符串.
     */
    public static String toSBC(String input) {
        return toSBC(input, null);
    }

    /**
     * 半角转全角
     *
     * @param input         String
     * @param notConvertSet 不替换的字符集合
     * @return 全角字符串.
     */
    public static String toSBC(String input, Set<Character> notConvertSet) {
        char c[] = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (null != notConvertSet && notConvertSet.contains(c[i])) {
                // 跳过不替换的字符
                continue;
            }

            if (c[i] == ' ') {
                c[i] = '\u3000';
            } else if (c[i] < '\177') {
                c[i] = (char) (c[i] + 65248);

            }
        }
        return new String(c);
    }

    /**
     * 全角转半角
     *
     * @param input String.
     * @return 半角字符串
     */
    public static String toDBC(String input) {
        return toDBC(input, null);
    }

    /**
     * 替换全角为半角
     *
     * @param text          文本
     * @param notConvertSet 不替换的字符集合
     * @return 替换后的字符
     */
    public static String toDBC(String text, Set<Character> notConvertSet) {
        char c[] = text.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (null != notConvertSet && notConvertSet.contains(c[i])) {
                // 跳过不替换的字符
                continue;
            }

            if (c[i] == '\u3000') {
                c[i] = ' ';
            } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
                c[i] = (char) (c[i] - 65248);
            }
        }
        String returnString = new String(c);

        return returnString;
    }

6)、数字金额大写转换:

 

  /**
     * 数字金额大写转换 先写个完整的然后将如零拾替换成零
     *
     * @param n 数字
     * @return 中文大写数字
     */
    public static String digitUppercase(double n) {
        String[] fraction = {"角", "分"};
        String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};

        String head = n < 0 ? "负" : "";
        n = Math.abs(n);

        String s = "";
        for (int i = 0; i < fraction.length; i++) {
            s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
        }
        if (s.length() < 1) {
            s = "整";
        }
        int integerPart = (int) Math.floor(n);

        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            String p = "";
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[integerPart % 10] + unit[1][j] + p;
                integerPart = integerPart / 10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }

 

 

3、日期类:

(1)、取得当前年、月、日:

  /**
     * 取得当前年的年份
     *
     * @return int
     */
    public static int getYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 取得当前月的月份
     *
     * @return int
     */
    public static int getMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH);
    }

    /**
     * 取得当前日的日期
     *
     * @return int
     */
    public static int getDay() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DATE);
    }

(2)、格式化时间,时间转字符串:

  /**
     * 格式化时间,时间转字符串
     *
     * @param date null则为当前系统时间
     * @param format 格式,null则默认为:'yyyy-MM-dd HH:mm:ss'
     * @return 字符串格式的日期
     */
    public static String getDateTimeByStr(Date date, String format) {
        if (date == null) {
            date = new Date();
        }
        if (format == null) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        return new SimpleDateFormat(format).format(date);
    }

(3)、获取两时间相隔月份:

  /**
     * 两时间相隔月份
     * @param startDate
     * @param endDate
     * @return
     */
    public static Integer getDiffMonth(Date startDate, Date endDate){
        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        start.setTime(startDate);
        end.setTime(endDate);
        int result = end.get(Calendar.MONTH) - start.get(Calendar.MONTH);
        int month = (end.get(Calendar.YEAR) - start.get(Calendar.YEAR)) * 12;
        return Math.abs(month + result);
    }

(4)、获得特定日期之后的固定天数的某一天:

  /**
     * @param date 传入的日期
     * @param days 要增加的天数
     * @return Date  获取的目标日期
     *
     * 获得特定日期之后的固定天数的某一天
     */
    public static Date addDays(Date date, int days) {
        Date date1 = null;
        try {
            if (null == date) {
                return date1;
            }
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DATE, days);
            date1 = calendar.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return date1;
        }
    }

(5)、获得特定日期之前的固定天数的某一天:

    /**
     * @param date 传入的日期
     * @param days 要回退的天数
     * @return Date  获取的目标日期
     *
     * 获得特定日期之前的固定天数的某一天
     */
    public static Date getPastDate(Date date, int days) {
        Date date1 = null;
        try {
            if (null == date) {
                return date1;
            }
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - days);
            date1 = calendar.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return date1;
        }
    }
    /**
     * 获得特定日期之前的固定天数的某一天的开始时间
     *
     * @param date 传入的日期
     * @param days 要回退的天数
     * @return Date  获取的目标日期
     *
     */
    public static String getStartOfDay(Date date, int days) {
        Date startDate = null;
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - days);
            calendar.getTime();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(calendar.getTime().getTime()),
                    ZoneId.systemDefault());
            LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
            startDate =  Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startDate);
        }
    }

    /**
     * 获得特定日期之前的固定天数的某一天的结束时间
     *
     * @param date 传入的日期
     * @param days 要回退的天数
     * @return Date  获取的目标日期
     *
     */
    public static String getEndOfDay(Date date, int days) {
        Date endDate = null;
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - days);
            calendar.getTime();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(calendar.getTime().getTime()),
                    ZoneId.systemDefault());
            LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
            endDate =  Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endDate);
        }
    }

 

(6)、获取日期相减后的天数:

  /**
     * @param minuendDate 被减数日期
     * @param subDate     减数日期
     * @return int    相差的天数
     *
     * 获得日期相减后的天数
     */
    public static int subDate(Date minuendDate, Date subDate) {
        if (minuendDate != null && subDate != null) {
            long timeMillions = (minuendDate.getTime() - subDate.getTime()) % (24 * 60 * 60 * 1000);
            int days = new Long((minuendDate.getTime() - subDate.getTime()) / (24 * 60 * 60 * 1000)).intValue();
            if (timeMillions == 0) {
                return days;
            } else {
                return days + 1;
            }
        } else {
            return 0;
        }

    }

 

(7)、获取昨天凌晨后第i刻的时间:

    /**
     * 获取昨天凌晨后第i刻的时间
     * @return Date
     * */
    private static Date getYesterdayQuarter(int i) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.DATE, -1);    //得到前一天
        calendar.add(Calendar.MINUTE, i * 15);
        Date date = calendar.getTime();
        return date;
    }

 

(8)、获取当前时间对应的昨天第i刻时间:

    /**
     * 获取当前时间对应的昨天第i刻时间
     * @return Date
     * */
    private static Date getYesterdayDate(int i) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.DATE, -1);    //得到前一天
        calendar.add(Calendar.MINUTE, i * 15);
        Date date = calendar.getTime();
        return date;
    }

 

(9)、获取今天凌晨后第i刻的时间:

    /**
     * 获取今天凌晨后第i刻的时间
     * @return Date
     * */
    private static Date getNowQuarter(int i) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.MINUTE, i * 15);
        Date date = calendar.getTime();
        return date;
    }

 

(10)、计算两时间相差的分钟数:

    /**
     * 计算两时间相差的分钟数
     * @return long
     * */
    private static long getDifferenceMinute(Date startDate, Date endDate) {
        long between = (endDate.getTime() - startDate .getTime())/1000;
        long min = between/60;
        return  min;
    }

 

 4、网络工具类:

(1)、根据CIDR返回IPV6网络地址信息:

(2)、获取IPV6地址的二进制分段数据:

(3)、获取IPV6地址的十进制数据:

(4)、根据CIDR返回IPV6网络起始/结束地址信息的十进制数组:

(5)、将IPV6网络十进制整数形式转换为字符串形式(最简IPV6地址格式):

(6)、校验IPV6是否合法:

(7)、获取全格式IPV6地址信息:

(8)、获取最简格式IPV6地址信息:

(9)、校验IPV6地址是否在某网段掩码中:

(10)、返回从给定的IPV6地址后的所有规划的IPV6地址信息:

工具类:

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.Normalizer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class IPManageUtils {

    /**
     * 根据CIDR返回IPV6网络地址信息
     *
     * @Param cidr: 例:"1101:6723:5B06:0001:0000:0004:2000:2F00/119"
     */
    public static List<String> getIpv6ListByCidr(String cidr) {
        List<String> list = new ArrayList<>();
        try {
            BigInteger[] ipv6Integer = getIpv6StartAndEndByCidr(cidr);
            BigInteger ipv6IntegerStart = ipv6Integer[0];
            BigInteger ipv6IntegerEnd = ipv6Integer[1];

            while (true) {
                String ip = int10Toipv6(ipv6IntegerStart);
                list.add(ip);
                //+1操作
                ipv6IntegerStart = ipv6IntegerStart.add(BigInteger.ONE);
                if (ipv6IntegerStart.compareTo(ipv6IntegerEnd) == 1) {
                    break;
                }
            }
            return list;
        } catch (Exception e){
            log.error("CIDR:{}格式错误", cidr);
            return list;
        }
    }

    /**
     * 获取IPV6地址的二进制分段数据(返回-1说明给定的ipv6不合法)
     *
     * @return: 十六进制转二进制
     * @throws UnknownHostException
     */
    public static String subsectionIpv6To2(String ipv6) throws UnknownHostException {
        if (isValidIpv6Addr(ipv6)) {
            ipv6 = completIpv6(ipv6);
            String[] split = ipv6.split(":");
            String tmpString = "";
            if (split.length == 8) {
                for (int i = 0; i < split.length; i++) {
                    String str = Long.toBinaryString(Long.valueOf(split[i], 16));
                    tmpString += str + ":";
                }
            }
            return tmpString.substring(0, tmpString.length() - 1);
        }
        return "-1";
    }

    /**
     * 获取IPV6地址的10进制数据
     *
     * @return
     */
    public static BigInteger ipv6ToBytesToBigInteger(String ipv6) {
        byte[] ret = new byte[17];
        ret[0] = 0;
        int ib = 16;
        boolean comFlag = false;// ipv4混合模式标记
        if (ipv6.startsWith(":"))// 去掉开头的冒号
            ipv6 = ipv6.substring(1);
        if (ipv6.endsWith("::")) {
            ipv6 = ipv6+"0";
        }
        String groups[] = ipv6.split(":");
        for (int ig = groups.length - 1; ig > -1; ig--) {// 反向扫描
            if (groups[ig].contains(".")) {
                // 出现ipv4混合模式
                byte[] temp = ipv4ToBytes(groups[ig]);
                ret[ib--] = temp[4];
                ret[ib--] = temp[3];
                ret[ib--] = temp[2];
                ret[ib--] = temp[1];
                comFlag = true;
            } else if ("".equals(groups[ig])) {
                // 出现零长度压缩,计算缺少的组数
                int zlg = 9 - (groups.length + (comFlag ? 1 : 0));
                while (zlg-- > 0) {// 将这些组置0
                    ret[ib--] = 0;
                    ret[ib--] = 0;
                }
            } else {
                int temp = Integer.parseInt(groups[ig], 16);
                ret[ib--] = (byte) temp;
                ret[ib--] = (byte) (temp >> 8);
            }
        }
        return new BigInteger(ret);
    }

    /**
     * 根据CIDR返回IPV6网络起始/结束地址信息的十进制数组
     *
     * @return
     */
    public static BigInteger[] getIpv6StartAndEndByCidr(String cidr) {
        try {
            cidr = cidr.trim();
            BigInteger[] info = new BigInteger[2];
            // 判断是否是具体IP
            int index = cidr.indexOf("/");
            if (index < 0) {
                info[0] = ipv6ToBytesToBigInteger(cidr);
                info[1] = ipv6ToBytesToBigInteger(cidr);
                if (info[0] == null || info[1] == null) {
                    return null;
                }
                return info;
            }
            String ipinfo = cidr.substring(0, index);
            Integer count = Integer.valueOf(cidr.substring(index + 1));
            StringBuffer mask = new StringBuffer();
            for (int i = 0; i < 128; i++) {
                if (i<count) {
                    mask.append("1");
                }else {
                    mask.append("0");
                }
            }
            String string = new BigInteger(mask.toString(),2).toString(10);
            BigInteger areaIp = ipv6ToBytesToBigInteger(ipinfo);
            info[0] = areaIp.and(new BigInteger(string));
            String re = mask.substring(mask.lastIndexOf("1")+1).replace("0", "1");
            info[1] = areaIp.or(new BigInteger(new BigInteger(re.toString(),2).toString(10)));
            if (info[0] == null || info[1] == null) {
                return null;
            }
            return info;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 将IPV6网络十进制整数形式转换为字符串形式(最简IPV6地址格式)
     * @return
     */
    public static String int10Toipv6(BigInteger big) {
        String str = "";
        BigInteger ff = BigInteger.valueOf(0xffff);
        for (int i = 0; i < 8; i++) {
            str = big.and(ff).toString(16) + ":" + str;

            big = big.shiftRight(16);
        }
        str = str.substring(0, str.length() - 1);

        return str.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");
    }

    /**
     * 校验ipv6是否合法
     *
     * @return
     */
    public static boolean isValidIpv6Addr(String ipAddr) {

        String regex = "^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){1,6})|(:(:[0-9A-Fa-f]{1,4}){1,7})|(([0-9A-Fa-f]{1,4}:){6}(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){0,4}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(:(:[0-9A-Fa-f]{1,4}){0,5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}))$";

        if (ipAddr == null || ipAddr.trim().length() == 0) {
            return false;
        }
        ipAddr = Normalizer.normalize(ipAddr, Normalizer.Form.NFKC);
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(ipAddr);

        boolean match = matcher.matches();
        return match;
    }

    /**
     *
     * 获取全格式IPV6地址信息(将ipv6每段补齐4位,如果返回-1说明给定的ipv6不合法)
     *
     * @return
     * @throws UnknownHostException
     */
    public static String completIpv6(String ipv6) throws UnknownHostException {
        StringBuffer str = new StringBuffer();
        if (isValidIpv6Addr(ipv6)) {
            String ip = InetAddress.getByName(ipv6).toString().replace("/", "");
            String[] info = ip.split(":");
            for (int i = 0; i < info.length; i++) {
                switch (info[i].length()) {
                    case 1:
                        info[i] = "000" + info[i];
                        break;
                    case 2:
                        info[i] = "00" + info[i];
                        break;
                    case 3:
                        info[i] = "0" + info[i];
                        break;
                    default:
                        break;
                }
                if (i < 7) {
                    str.append(info[i] + ":");
                } else {
                    str.append(info[i]);
                }
            }
        }else {
            return "-1";
        }
        return str.toString();
    }

    /**
     * 获取最简格式IPV6地址信息(将ipv6地址压缩为最简模式 ,如果返回-1说明给定的ipv6不合法)
     *
     * IPv6简写规范:
     * 1)每个IPv6地址段起始的0可以被省略;
     * 2)如果一段为4个零,可以简写为一个0
     * 3)如果有连续的多个段全为0,则可以使用::表示 注:一个地址段中只能有一个::出现,不可以出现两个及以上
     */
    public static String shortedIpv6(String ipv6) {
        if (isValidIpv6Addr(ipv6)) {
            String shortIP="";
            String[] arr = ipv6.split(":");
            //去掉每组数据前的0
            for (int i = 0; i < arr.length; i++){
                arr[i] = arr[i].replaceAll("^0{1,3}", "");
            }
            //最长的连续0
            String[] arr2 = arr.clone();
            for (int i = 0; i < arr2.length; i++){
                if (!"0".equals(arr2[i])){
                    arr2[i] = "-";
                }
            }
            Pattern pattern = Pattern.compile("0{2,}");
            Matcher matcher = pattern.matcher(StringUtils.join(Arrays.asList(arr2), ""));
            String maxStr= "";
            int start = -1;
            int end = -1;
            while (matcher.find()) {
                if(maxStr.length()<matcher.group().length()) {
                    maxStr=matcher.group();
                    start = matcher.start();
                    end = matcher.end();
                }
            }
            // 组合IPv6简写地址
            if(maxStr.length()>0) {
                for (int i = start; i < end; i++){
                    arr[i] = ":";
                }
            }
            shortIP = StringUtils.join(Arrays.asList(arr), ":");
            shortIP= shortIP.replaceAll(":{2,}", "::");
            return shortIP;
        }
        return "-1";
    }

    /**
     * 校验ipv6地址是否在某网段掩码中
     *
     * @Param(iparea):参数可以是CIDR,或IPV6地址
     * @throws Exception
     */
    public static boolean ipv6IsInRange(String ipv6, String iparea) throws Exception {
        int suffix = 0;
        if (iparea.contains("/")) {
            suffix = Integer.parseInt(iparea.substring(iparea.indexOf("/") + 1));
            iparea = iparea.substring(0, iparea.indexOf("/"));
        }
        BigInteger ipv6Big = ipv6ToBytesToBigInteger(ipv6);
        BigInteger ipv6areaBig = ipv6ToBytesToBigInteger(iparea);

        BigDecimal ss = new BigDecimal(2);
        BigDecimal pow = ss.pow(128);
        BigInteger aa = new BigInteger(pow.toString());

        String str = aa.toString(2).replaceAll("0", "1").substring(1);
        BigInteger bb = new BigInteger(str, 2);
        String str1 = bb.shiftLeft(128 - suffix).toString(2);
        String str2 = str1.substring(128 - suffix, str1.length());

        BigInteger mask = new BigInteger(str2, 2);

        return ipv6Big.and(mask).compareTo(ipv6areaBig.and(mask)) == 0 ? true : false;
    }

    /**
     * 返回从给定的ipv6地址后的所有规划的ipv6地址信息
     *
     * @param ipv6Start 给定ipv6开始ip
     * @param count 规划需要IP数量
     * @return
     * @throws UnknownHostException
     */
    public static List<String> getIpv6List(String ipv6Start , int count) throws UnknownHostException {
        List<String> list = new ArrayList<>();
        if(isValidIpv6Addr(ipv6Start)) {
            String ipv6 = completIpv6(ipv6Start);
            BigInteger ipv6IntegerStart = ipv6ToBytesToBigInteger(ipv6);
            BigInteger cou = new BigInteger(String.valueOf(count-1));
            BigInteger ipv6IntegerEnd = ipv6IntegerStart.add(cou);

            while(true){
                String ip = int10Toipv6(ipv6IntegerStart);
                list.add(ip);
                //+1操作
                ipv6IntegerStart = ipv6IntegerStart.add(BigInteger.ONE);
                if(ipv6IntegerStart.compareTo(ipv6IntegerEnd)==1) {
                    break;
                }
            }
        }
        return list;
    }

    private static long ipToLong(String strIP) {
        long[] ip = new long[4];
        String[] ipSec = strIP.split("\\.");
        for (int k = 0; k < 4; k++) {
            ip[k] = Long.valueOf(ipSec[k]);
        }

        return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
    }

    private static String longToIp(long ipaddress) {
        StringBuffer sb = new StringBuffer("");
        sb.append(String.valueOf((ipaddress >>> 24)));
        sb.append(".");
        sb.append(String.valueOf((ipaddress & 0x00FFFFFF) >>> 16));
        sb.append(".");
        sb.append(String.valueOf((ipaddress & 0x0000FFFF) >>> 8));
        sb.append(".");
        sb.append(String.valueOf((ipaddress & 0x000000FF)));
        return sb.toString();
    }

    private static byte[] ipv4ToBytes(String ipv4) {
        byte[] ret = new byte[5];
        ret[0] = 0;
        // 先找到IP地址字符串中.的位置
        int position1 = ipv4.indexOf(".");
        int position2 = ipv4.indexOf(".", position1 + 1);
        int position3 = ipv4.indexOf(".", position2 + 1);
        // 将每个.之间的字符串转换成整型
        ret[1] = (byte) Integer.parseInt(ipv4.substring(0, position1));
        ret[2] = (byte) Integer.parseInt(ipv4.substring(position1 + 1,
                position2));
        ret[3] = (byte) Integer.parseInt(ipv4.substring(position2 + 1,
                position3));
        ret[4] = (byte) Integer.parseInt(ipv4.substring(position3 + 1));
        return ret;
    }

    

}

相关测试:

    public static void main(String[] args) throws Exception {
        System.out.println(JSONObject.toJSONString(getIpv6ListByCidr("1101:6723:5B06:0001:0000:0000:2000:2F00/119")));
        System.out.println(JSONObject.toJSONString(getIpv6ListByCidr("1101:6723:5B06:0001:0000:0000:2000:2F00/119").size()));
        BigInteger[] a = getIpv6StartAndEndByCidr("1101:6723:5B06:0001:0000:0000:2000:2F00/119");
        System.out.println(JSONObject.toJSONString(a));

        System.out.println(int10Toipv6(a[0]));
        System.out.println(int10Toipv6(a[1]));

        System.out.println(isValidIpv6Addr("1101:6723:5b06:1::2000:2ffd"));

        System.out.println(completIpv6("1101:6723:5b06:1::2000:2ffd"));
        System.out.println(shortedIpv6("1101:6723:5b06:0001:0000:0000:2000:2ffd"));

        System.out.println(ipv6ToBytesToBigInteger("1101:6723:5b06:1::2000:2e00"));
        System.out.println(ipv6ToBytesToBigInteger("1101:6723:5b06:0001:0000:0000:2000:2e00"));

        System.out.println(subsectionIpv6To2("1101:6723:5b06:1::2000:2e00"));

        System.out.println(ipv6IsInRange("1101:6723:5b06:0001:0000:0000:2000:2e00", "1101:6723:5b06:1::2000:2e00"));

        System.out.println(JSONObject.toJSONString(getIpv6List("1101:6723:5b06:1::2000:2e09", 100)));

    }

 

 

 

 

posted on 2022-05-13 23:42  爱文(Iven)  阅读(59)  评论(0编辑  收藏  举报

导航