MySQL中以数值类型存储IP地址
前言
数据库中存储IP地址的时候,推荐使用整数存储而不是字符串。一般来说, 在保证正确性的前提下,尽量使用最小的数据类型来存储和展示数据;小的数据类型一般比大的更快,因为小的数据类型占用的磁盘空间,内存和cup缓存都相对小,需要的cpu处理也要相对少; 这个原则很重要,设计的时候不要低估待存储数据的数据范围。另外,转换之后,还便于使用范围查询(BETWEEN...AND),且效率更高。
对于转换来说,MySQL提供了相关的函数来把字符串格式的IP转换成整数INET_ATON
,以及把整数格式的IP转换成字符串的INET_NTOA
。如下所示:
mysql> select inet_aton('192.168.0.1');
+--------------------------+
| inet_aton('192.168.0.1') |
+--------------------------+
| 3232235521 |
+--------------------------+
1 row in set (0.00 sec)
mysql> select inet_ntoa(3232235521);
+-----------------------+
| inet_ntoa(3232235521) |
+-----------------------+
| 192.168.0.1 |
+-----------------------+
1 row in set (0.00 sec)
对于IPv6来说,使用VARBINARY
可获得相同的好处,同时MySQL也提供了转换函数INET6_ATON
和INET6_NTOA
。
IPv4地址和int类型数字互转
package com.hoss.ext.authentication;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* IPv4地址和int类型数字互转
*
* @author Wiener
* @date 2021/4/29
*/
public class SaveIp {
public static void main(String[] args) {
String ip = "127.0.0.1";
String ip33 = "172.16.24.33";
String ip13 = "172.16.10.13";
String ip89 = "111.112.113.114";
intToIp(ipToInt(ip89));
}
/**
* (Ip转Integer)
* 方法名:ipToInt
*
* @throws
* @since 1.0.0
*/
public static int ipToInt(String ip) {
if (!isIPv4Address(ip)) {
throw new RuntimeException("Invalid ip address");
}
String[] ips = ip.split("\\.");
int ipInt = 0;
//因为每个位置最大255,刚好在2进制里表示8位
for (String ip4 : ips) {
Integer ip4a = Integer.parseInt(ip4);
//这里应该用+也可以,但是位运算更快
ipInt = (ipInt << 8) | ip4a;
}
System.out.println(ipInt);
return ipInt;
}
/**
* 判断是否为ipv4地址
*
* @param ipv4Addr
* @return true 是ipv4地址
*/
private static boolean isIPv4Address(String ipv4Addr) {
// 0-255的数字
String lower = "(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])";
String regex = lower + "(\\." + lower + "){3}";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(ipv4Addr);
return matcher.matches();
}
/**
* (Integer转IP)
* 方法名:intToIp
*
* @param ip数字
* @return String
*/
public static String intToIp(int ip) {
//思路很简单,每8位拿一次,就是对应位的IP
StringBuilder sb = new StringBuilder();
for (int i = 3; i >= 0; i--) {
int ipa = (ip >> (8 * i)) & (0xff);
sb.append(ipa + ".");
}
sb.delete(sb.length() - 1, sb.length());
System.out.println("数字转IP:" + sb);
return sb.toString();
}
}
Reference
读后有收获,小礼物走一走,请作者喝咖啡。
Buy me a coffee. ☕Get red packets.
作者:楼兰胡杨
本文版权归作者和博客园共有,欢迎转载,但请注明原文链接,并保留此段声明,否则保留追究法律责任的权利。