首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java IP 地址與 int/long 互轉工具類:位運算高效實現

     編輯:Java 相關知識

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
  • 字串 → 整數: 分割四段 → 各段左移 24/16/8/0 位 → 位或合併。
  • 整數 → 字串: 依次無符號右移 24/16/8/0 位 → 與 0xFF 位與 → 取得四段 → 字串拼接。

完整工具類:IpConverter

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

Java 8+ 內建替代方案:InetAddress

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 解析開銷(即使緩存),批量轉換較慢。

資料庫存儲建議

資料庫推薦欄位類型備註
MySQLINT UNSIGNED4 字節,需插入時 INET_ATON()、查詢 INET_NTOA()
PostgreSQLINET 或 BIGINTINET 內建網段運算子
RedisString (IP 字串) 或 Sorted Set (score=long)Sorted Set 適合範圍查詢

IPv6 提示

IPv6 為 128 位,需用 BigInteger 或兩個 long 存儲。Java Inet6Address 可取得 16 字節陣列,轉換邏輯類似但位寬加倍。生產環境建議直接使用 InetAddress 物件或專用庫(如 ipaddress)。

總結

  • ✅ **高頻轉換**用手寫位運算(IpConverter),零依賴、極快。
  • ✅ **低頻/請求級**用 JDK InetAddress,可讀性強。
  • ✅ 資料庫採用 **UNSIGNED INT / INET** 類型,配合內建函數。
  • ✅ 牢記 **無符號右移 >> 與 & 0xFF** 是關鍵。

掌握 IP 與整數互轉,是網路程式開發與大數據 IP 畫像的基礎技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved