2011-03-28 124 views
2

我有一個數據庫,存儲所有使用過某個功能的用戶的IP號碼(即:投票投票),我想避免同一用戶或IP投票兩次。數據庫存儲IP壓縮

因此,我一直在存儲投票在我的民意調查中的匿名用戶的所有IP。我的數據庫充滿了IP,如123.456.789 ...

但是,這是低效的,是否有單向函數壓縮和IP到一個較短的字符串?

像123.456.798 =>%DA

回答

2

對於IPv4可以壓縮的IP地址轉換成一個int這樣的:

Scanner scanner = new Scanner(ip).useDelimiter("\\."); 
int value = (scanner.nextInt() << 24) | (scanner.nextInt() << 16) 
     | (scanner.nextInt() << 8) | scanner.nextInt(); 

這可太逆轉:

String ip = ((value >> 24) & 0xFF) + "." + ((value >> 16) & 0xFF) 
     + "." + ((value >> 8) & 0xFF) + "." + (value & 0xFF); 
+0

這是可逆的嗎? – 2011-03-28 03:58:31

+0

@穆罕默德:是的,它是可逆的。我會用反向代碼更新答案。 – WhiteFang34 2011-03-28 04:00:53

0

假設你不支持IPv6,IP地址在一個int適合。你真的需要更小的東西?

而且如果你支持IPv6,兩個多頭就可以。仍然看起來很小。

+0

對不起,我一定錯過了什麼。如何將IPv4轉換爲int或IPv6轉換爲兩個整數?我在想像2字節的東西 – somid3 2011-03-28 03:54:50

+0

@somid - 你不能把4字節的數據放在2字節桶中。 – 2011-03-28 03:59:29

1

IPv4地址是32位。在虛線表示法中,您可以使用最多15個字節的字符串,該字符串仍表示32位(4字節)地址。顯而易見的步驟是將它們轉換爲二進制格式,例如inet_atoninet_pton。後者通常建議用於新代碼,因爲除了IPv4外,它還處理IPv6地址。

如果你需要超越,可能嘗試存儲地址在一個trie中。雖然這並不適合你的普通數據庫模型,但是,除非你真的有lot或匿名用戶,否則 可能不是 可能是不值得的麻煩。

2

如果您將它們作爲字符串存儲在數據庫中,那麼這樣做會很浪費。在存儲它們之前,可以將它們轉換爲4個字節的整數。

java.net.InetAddress類有一個getByName方法,它將返回一個新的InetAddress對象。在返回的對象上調用getAddress會得到一個地址的字節數組,您可以很容易地將它轉換爲int。

請注意,InetAddress也可以使用IPv6地址,因此您需要確保可以將它們存儲在數據庫中,或者檢查getByName調用返回的InetAddress的類型以確保它是IPv4地址。