如果我有一对IP地址,如:
IP1="168.2.65.33"
IP2="192.4.2.55"
我想将每对编码为64位值,以便前32位是第一个IP地址,第二个是第二个IP地址。然后,我希望能够将64位值保存到文件中,以便我可以将其读回并恢复两个IP地址。
目标是节省空间。
是否可以在python中执行此操作?
答案 0 :(得分:5)
不要担心以64位编码。 IPv4地址是32位(4字节)。如果将其中两个写入文件,则大小为8个字节。
使用socket.inet_aton
将人类可读的IP地址 string 转换为压缩二进制原始4字节字符串:
import socket
ip_addrs = ["168.2.65.33", "192.4.2.55"]
with open('data.out', 'wb') as f:
for ip in ip_addrs:
raw = socket.inet_aton(ip)
f.write(raw)
结果:
$ hexdump -Cv data.out
00000000 a8 02 41 21 c0 04 02 37 |..A!...7|
00000008
互补转换函数socket.inet_ntoa
将打包的4字节字符串转换回人类可读的IP地址。
以下是编写和阅读它们的示例:
import socket
ip_pairs = [
('1.1.1.1', '1.1.1.2'),
('2.2.2.2', '2.2.2.3'),
('3.3.3.3', '3.3.3.4'),
]
# Write them out
with open('data.out', 'wb') as f:
for ip1, ip2 in ip_pairs:
raw = socket.inet_aton(ip1) + socket.inet_aton(ip2)
f.write(raw)
def read_with_eof(f, n):
res = f.read(n)
if len(res) != n:
raise EOFError
return res
# Read them back in
result = []
with open('data.out', 'rb') as f:
while True:
try:
ip1 = socket.inet_ntoa(read_with_eof(f, 4))
ip2 = socket.inet_ntoa(read_with_eof(f, 4))
result.append((ip1, ip2))
except EOFError:
break
print 'Input:', ip_pairs
print 'Result:', result
输出:
$ python pairs.py
Input: [('1.1.1.1', '1.1.1.2'), ('2.2.2.2', '2.2.2.3'), ('3.3.3.3', '3.3.3.4')]
Result: [('1.1.1.1', '1.1.1.2'), ('2.2.2.2', '2.2.2.3'), ('3.3.3.3', '3.3.3.4')]
答案 1 :(得分:1)
是的,有可能,就像这样:
import struct
import os
IP1="168.2.65.233"
IP2="192.4.2.55"
s = struct.pack('>8B', *map(int, IP1.split('.') + IP2.split('.')))
with open('f', 'wb') as f:
f.write(s)
print(os.stat('f').st_size) #: 8.
这适用于Python 2和3。
根据Jonathon Reinhart的回答,您还可以使用socket.inet_aton
代替struct.pack
。
答案 2 :(得分:1)
在Python3中,有一个用于处理IP的ipaddress
模块。将它们分成32位并将它们加在一起:
from ipaddress import ip_address
original1 = ip_address('192.168.0.1')
original2 = ip_address('8.8.8.8')
out = original1.packed + original2.packed
将它们装回:
loaded1 = ip_address(out[0:4])
loaded2 = ip_address(out[4:])