我应该如何执行从 IPv6 到长整型的转换,反之亦然?
到目前为止我已经:
public static long IPToLong(String addr) {
String[] addrArray = addr.split("\\.");
long num = 0;
for (int i = 0; i < addrArray.length; i++) {
int power = 3 - i;
num += ((Integer.parseInt(addrArray[i], 16) % 256 * Math.pow(256, power)));
}
return num;
}
public static String longToIP(long ip) {
return ((ip >> 24) & 0xFF) + "."
+ ((ip >> 16) & 0xFF) + "."
+ ((ip >> 8) & 0xFF) + "."
+ (ip & 0xFF);
}
这是正确的解决方案还是我错过了什么?
(如果该方案同时适用于ipv4和ipv6那就完美了)
您也可以使用
java.net.InetAddress
。它适用于 ipv4 和 ipv6(所有格式)。
原始答案已更新为根据 OTrains 的评论使用无符号整数。
public static BigInteger ipToBigInteger(String addr) throws UnknownHostException {
InetAddress a = InetAddress.getByName(addr);
byte[] bytes = a.getAddress();
return new BigInteger(1, bytes);
}
IPv6 地址是一个 128 位数字,如此处所述。 Java 中的 long 以 64 位表示,因此您需要另一个结构,例如 BigDecimal 或两个 long(包含两个 long 数组的容器或简单的两个 long 数组)来存储 IPv6 地址。
下面是一个例子(仅供参考):
public class Asd {
public static long[] IPToLong(String addr) {
String[] addrArray = addr.split(":");//a IPv6 adress is of form 2607:f0d0:1002:0051:0000:0000:0000:0004
long[] num = new long[addrArray.length];
for (int i=0; i<addrArray.length; i++) {
num[i] = Long.parseLong(addrArray[i], 16);
}
long long1 = num[0];
for (int i=1;i<4;i++) {
long1 = (long1<<16) + num[i];
}
long long2 = num[4];
for (int i=5;i<8;i++) {
long2 = (long2<<16) + num[i];
}
long[] longs = {long2, long1};
return longs;
}
public static String longToIP(long[] ip) {
String ipString = "";
for (long crtLong : ip) {//for every long: it should be two of them
for (int i=0; i<4; i++) {//we display in total 4 parts for every long
ipString = Long.toHexString(crtLong & 0xFFFF) + ":" + ipString;
crtLong = crtLong >> 16;
}
}
return ipString;
}
static public void main(String[] args) {
String ipString = "2607:f0d0:1002:0051:0000:0000:0000:0004";
long[] asd = IPToLong(ipString);
System.out.println(longToIP(asd));
}
}
IPv6地址不能长期存储。您可以使用 BigInteger 而不是 long。
public static BigInteger ipv6ToNumber(String addr) {
int startIndex=addr.indexOf("::");
if(startIndex!=-1){
String firstStr=addr.substring(0,startIndex);
String secondStr=addr.substring(startIndex+2, addr.length());
BigInteger first=ipv6ToNumber(firstStr);
int x=countChar(addr, ':');
first=first.shiftLeft(16*(7-x)).add(ipv6ToNumber(secondStr));
return first;
}
String[] strArr = addr.split(":");
BigInteger retValue = BigInteger.valueOf(0);
for (int i=0;i<strArr.length;i++) {
BigInteger bi=new BigInteger(strArr[i], 16);
retValue = retValue.shiftLeft(16).add(bi);
}
return retValue;
}
public static String numberToIPv6(BigInteger ipNumber) {
String ipString ="";
BigInteger a=new BigInteger("FFFF", 16);
for (int i=0; i<8; i++) {
ipString=ipNumber.and(a).toString(16)+":"+ipString;
ipNumber = ipNumber.shiftRight(16);
}
return ipString.substring(0, ipString.length()-1);
}
public static int countChar(String str, char reg){
char[] ch=str.toCharArray();
int count=0;
for(int i=0; i<ch.length; ++i){
if(ch[i]==reg){
if(ch[i+1]==reg){
++i;
continue;
}
++count;
}
}
return count;
}
维诺德的回答是正确的。但还有一些地方可以改进。
首先,在'countChar'方法中,'continue'应该替换为'break'。
其次,必须考虑一些边界条件。
public static BigInteger ipv6ToNumber(String addr) {
int startIndex = addr.indexOf("::");
if (startIndex != -1) {
String firstStr = addr.substring(0, startIndex);
String secondStr = addr.substring(startIndex + 2, addr.length());
BigInteger first = new BigInteger("0");
BigInteger second = new BigInteger("0");
if (!firstStr.equals("")) {
int x = countChar(addr, ':');
first = ipv6ToNumber(firstStr).shiftLeft(16 * (7 - x));
}
if (!secondStr.equals("")) {
second = ipv6ToNumber(secondStr);
}
first = first.add(second);
return first;
}
String[] strArr = addr.split(":");
BigInteger retValue = BigInteger.valueOf(0);
for (int i = 0; i < strArr.length; i++) {
BigInteger bi = new BigInteger(strArr[i], 16);
retValue = retValue.shiftLeft(16).add(bi);
}
return retValue;
}
public static int countChar(String str, char reg){
char[] ch=str.toCharArray();
int count=0;
for(int i=0; i<ch.length; ++i){
if(ch[i]==reg){
if(ch[i+1]==reg){
++i;
break;
}
++count;
}
}
return count;
}
以下是如何使用开源 IPAddress Java 库 来完成此操作。免责声明:我是该图书馆的项目经理。
String address = "aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222";
BigInteger val = new IPAddressString(address).getAddress().getValue();