IPv4 地址 (如 192.168.1.1) 本質是 32 位無符號整數。Java 無無符號類型,通常用 long 存儲 (範圍 0 ~ 4,294,967,295)。本文提供健壯的工具方法,含輸入校驗、位運算轉換、異常防護。
public static long ipToLong(String ip) {
if (ip == null || ip.isEmpty()) return 0L;
// 1. 清洗輸入:只保留數字和點
String cleaned = ip.replaceAll("[^0-9.]", "").trim();
// 2. 分割四段
String[] parts = cleaned.split("\\.");
if (parts.length != 4) {
throw new IllegalArgumentException("Invalid IPv4 format: " + ip);
}
// 3. 解析並位移拼接 (無符號右移 >>> 0 確保正數)
long result = 0L;
for (int i = 0; i < 4; i++) {
int octet = Integer.parseInt(parts[i]);
if (octet < 0 || octet > 255) {
throw new IllegalArgumentException("Octet out of range 0-255: " + octet);
}
result = (result << 8) | (octet & 0xFFL);
}
return result;
}
IP: 192 . 168 . 1 . 1
↓ ↓ ↓ ↓
11000000 10101000 00000001 00000001 (二進制)
↓ ↓ ↓ ↓
<< 24 << 16 << 8 << 0
↓ ↓ ↓ ↓
3232235777 (十進制 long = 0xC0A80101)
public final class IpUtil {
private IpUtil() {}
/** IPv4 字符串 → long (無符號 32 位) */
public static long ipToLong(String ip) {
if (ip == null) return 0L;
String cleaned = ip.replaceAll("[^0-9.]", "").trim();
String[] parts = cleaned.split("\\.");
if (parts.length != 4) throw new IllegalArgumentException("Invalid IPv4: " + ip);
long result = 0L;
for (String part : parts) {
int octet = Integer.parseInt(part);
if (octet < 0 || octet > 255) throw new IllegalArgumentException("Octet 0-255: " + octet);
result = (result << 8) | (octet & 0xFFL);
}
return result;
}
/** long → IPv4 字符串 */
public static String longToIp(long ipLong) {
// 無符號右移 >>> 確保高位補 0
return ((ipLong >>> 24) & 0xFF) + "." +
((ipLong >>> 16) & 0xFF) + "." +
((ipLong >>> 8) & 0xFF) + "." +
(ipLong & 0xFF);
}
/** 校驗合法 IPv4 */
public static boolean isValidIpv4(String ip) {
if (ip == null) return false;
String regex = "^((25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)$";
return ip.matches(regex);
}
// 單元測試示例
public static void main(String[] args) {
String ip = "192.168.1.1";
long l = ipToLong(ip); // 3232235777
String back = longToIp(l); // "192.168.1.1"
System.out.println(ip + " -> " + l + " -> " + back);
assert ip.equals(back);
// 邊界測試
System.out.println("0.0.0.0 -> " + ipToLong("0.0.0.0")); // 0
System.out.println("255.255.255.255 -> " + ipToLong("255.255.255.255")); // 4294967295
}
}
| 坑點 | 後果 | 修正 |
|---|---|---|
用 int 接收 | 高位符號位導致負數,比較/存儲錯誤 | 統一用 long,數據庫用 BIGINT UNSIGNED 或 DECIMAL(10,0) |
直接 Long.parseLong 不校驗 | 非法輸入拋 NumberFormatException 或產生錯誤值 | 正則校驗 + 分段解析 + 範圍檢查 |
忽略 BOM/隱形字符 (如 \uFEFF) | 解析失敗 For input string: \"\uFEFF0\" | 調用前 ip = ip.replaceAll("\\p{C}", "").trim() 移除控制字符 |
符號右移 >> 而非無符號 >>>> | 高位補 1 導致反解錯誤 | 反解時**全部用 >>>>** |
BETWEEN)。IPv4 String ⇄ Long 轉換核心是 **8 位分段位移拼接/拆解**,關鍵在 **輸入清洗校驗**、**無符號右移 >>>>**、**長整型存儲**。封裝為工具類並覆蓋邊界測試,即可安全用於生產環境。