IPv4 地址本質是 32 位無符號整數。在資料庫存儲、網段判斷、IP 範圍查詢等場景,將點分十進制字串(如 192.168.1.1)與整數互轉可大幅提升效能。本文提供 **純位運算實現**、**無符號處理細節**、**Java 8+ 內建工具類**與 **IPv6 擴展提示**的完整工具類。
IP: 192.168.1.1 二進制: 11000000 10101000 00000001 00000001 整數: (192 << 24) | (168 << 16) | (1 << 8) | 1 = 3232235777
public final class IpConverter {
private IpConverter() {}
/** IPv4 字串轉無符號長整數 (0 ~ 4294967295) */
public static long ipToLong(String ip) {
if (ip == null || ip.isEmpty()) return 0L;
String[] seg = ip.split("\\.");
if (seg.length != 4) throw new IllegalArgumentException("非法 IPv4 格式: " + ip);
long result = 0L;
for (int i = 0; i < 4; i++) {
int val = Integer.parseInt(seg[i]);
if (val < 0 || val > 255) throw new IllegalArgumentException("段值超出範圍: " + val);
result = (result << 8) | (val & 0xFF);
}
return result;
}
/** 無符號長整數轉 IPv4 字串 */
public static String longToIp(long ipLong) {
StringBuilder sb = new StringBuilder(15);
for (int shift = 24; shift >= 0; shift -= 8) {
sb.append((ipLong >> shift) & 0xFF);
if (shift > 0) sb.append('.');
}
return sb.toString();
}
/** 有符號 int 轉換(資料庫 INT UNSIGNED 讀取時) */
public static long unsignedIntToLong(int signedInt) {
return signedInt & 0xFFFFFFFFL;
}
public static int longToUnsignedInt(long unsignedLong) {
return (int) unsignedLong; // Java int 儲存位模式相同,僅解釋不同
}
// 測試
public static void main(String[] args) {
String ip = "192.168.1.1";
long l = ipToLong(ip);
System.out.println(ip + " -> " + l); // 3232235777
System.out.println(l + " -> " + longToIp(l)); // 192.168.1.1
// 負數 int 還原
int signed = -1062731519; // 192.168.1.1 的有符號 int 表示
System.out.println("signed int " + signed + " -> " + longToIp(unsignedIntToLong(signed)));
}
}
import java.net.InetAddress;
import java.nio.ByteBuffer;
public static long ipToLongJdk(String ip) throws UnknownHostException {
byte[] bytes = InetAddress.getByName(ip).getAddress(); // 4 bytes
return ByteBuffer.wrap(bytes).getInt() & 0xFFFFFFFFL;
}
public static String longToIpJdk(long ipLong) {
byte[] bytes = ByteBuffer.allocate(4).putInt((int) ipLong).array();
try {
return InetAddress.getByAddress(bytes).getHostAddress();
} catch (UnknownHostException e) {
throw new IllegalArgumentException(e);
}
}
優點: 標準庫、自動處理主機序/網路序。**缺點: 涉及 DNS 解析開銷(即使緩存),批量轉換較慢。
| 資料庫 | 推薦欄位類型 | 備註 |
|---|---|---|
| MySQL | INT UNSIGNED | 4 字節,需插入時 INET_ATON()、查詢 INET_NTOA() |
| PostgreSQL | INET 或 BIGINT | INET 內建網段運算子 |
| Redis | String (IP 字串) 或 Sorted Set (score=long) | Sorted Set 適合範圍查詢 |
IPv6 為 128 位,需用 BigInteger 或兩個 long 存儲。Java Inet6Address 可取得 16 字節陣列,轉換邏輯類似但位寬加倍。生產環境建議直接使用 InetAddress 物件或專用庫(如 ipaddress)。
IpConverter),零依賴、極快。InetAddress,可讀性強。>> 與 & 0xFF** 是關鍵。掌握 IP 與整數互轉,是網路程式開發與大數據 IP 畫像的基礎技能。