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();
}
}
}