将 bytearray 从 VARBINARY(16) 列转换为 IP 地址
Convert bytearray from a VARBINARY(16) column into an IP address
我需要从 HP Vertica 数据库中提取大量数据并将其保存到文件中。我正在使用来自 Vertica 的官方 ODBC 驱动程序和 pyodbc。
这是我目前所做的:
cnxn = pyodbc.connect('DRIVER={Vertica};SERVER=localhost;DATABASE=db;UID=user;PWD=pw')
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
cnxn.setencoding(str, encoding='utf-8')
cnxn.setencoding(unicode, encoding='utf-8')
cur = cnxn.cursor()
cur.execute("SELECT * FROM schema.table LIMIT 3")
然后我读取数据
for row in cur:
print row
大多数字段返回得很好 - unicode 文本、数字或日期时间。但是对于存储 IP 地址的字段,我得到以下信息:
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
如何将其转换为文本?
非常感谢任何帮助!
谢谢!
VARBINARY(16) 是 128 位,正好适合 IPv6 地址的大小。示例数据解码为
0000:0000:0000:0000:0000:ffff:0a6f:195c
和维基百科关于 IPv6 的文章的 "IPv4-mapped IPv6 addresses" 小节(参考:here)说这样的地址是映射到 IPv6 格式(128 位)的 IPv4 地址(32 位) .
::ffff:10.111.25.92
我们可以使用如下函数从原始 bytearray
数据生成上述字符串表示形式:
def bytes_to_ip_address(byte_array):
if byte_array[0:12] == bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff'):
return '{0}.{1}.{2}.{3}'.format(byte_array[12], byte_array[13], byte_array[14], byte_array[15])
else:
return ':'.join(['{0:02x}{1:02x}'.format(byte_array[i], byte_array[i + 1]) for i in range(0, len(byte_array), 2)])
if __name__ == '__main__':
# examples
fld = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 10.111.25.92
fld = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 0100:0000:0000:0000:0000:ffff:0a6f:195c
或者,通过 Python3 我们可以使用 ipaddress 模块:
import ipaddress
def bytes_to_ip_address(byte_array):
ip6 = ipaddress.IPv6Address(bytes(byte_array))
ip4 = ip6.ipv4_mapped
if ip4 == None:
return str(ip6)
else:
return str(ip4)
if __name__ == '__main__':
# examples
fld = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 10.111.25.92
fld = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 100::ffff:a6f:195c
我看到有一个可接受的答案,但是...对于所有其他答案:
如果您的数据在 Vertica 中,非常 要做的第一件事就是查看很好的 SQL 参考手册。在这种情况下,您会发现一个内置函数,用于将表示为 VARBINARY 列的 IPv6 地址转换为字符串。
更简单,更快:
SELECT V6_NTOA(your_column_here) ;
我需要从 HP Vertica 数据库中提取大量数据并将其保存到文件中。我正在使用来自 Vertica 的官方 ODBC 驱动程序和 pyodbc。
这是我目前所做的:
cnxn = pyodbc.connect('DRIVER={Vertica};SERVER=localhost;DATABASE=db;UID=user;PWD=pw')
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
cnxn.setencoding(str, encoding='utf-8')
cnxn.setencoding(unicode, encoding='utf-8')
cur = cnxn.cursor()
cur.execute("SELECT * FROM schema.table LIMIT 3")
然后我读取数据
for row in cur:
print row
大多数字段返回得很好 - unicode 文本、数字或日期时间。但是对于存储 IP 地址的字段,我得到以下信息:
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
如何将其转换为文本?
非常感谢任何帮助!
谢谢!
VARBINARY(16) 是 128 位,正好适合 IPv6 地址的大小。示例数据解码为
0000:0000:0000:0000:0000:ffff:0a6f:195c
和维基百科关于 IPv6 的文章的 "IPv4-mapped IPv6 addresses" 小节(参考:here)说这样的地址是映射到 IPv6 格式(128 位)的 IPv4 地址(32 位) .
::ffff:10.111.25.92
我们可以使用如下函数从原始 bytearray
数据生成上述字符串表示形式:
def bytes_to_ip_address(byte_array):
if byte_array[0:12] == bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff'):
return '{0}.{1}.{2}.{3}'.format(byte_array[12], byte_array[13], byte_array[14], byte_array[15])
else:
return ':'.join(['{0:02x}{1:02x}'.format(byte_array[i], byte_array[i + 1]) for i in range(0, len(byte_array), 2)])
if __name__ == '__main__':
# examples
fld = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 10.111.25.92
fld = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 0100:0000:0000:0000:0000:ffff:0a6f:195c
或者,通过 Python3 我们可以使用 ipaddress 模块:
import ipaddress
def bytes_to_ip_address(byte_array):
ip6 = ipaddress.IPv6Address(bytes(byte_array))
ip4 = ip6.ipv4_mapped
if ip4 == None:
return str(ip6)
else:
return str(ip4)
if __name__ == '__main__':
# examples
fld = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 10.111.25.92
fld = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\')
print(bytes_to_ip_address(fld)) # 100::ffff:a6f:195c
我看到有一个可接受的答案,但是...对于所有其他答案:
如果您的数据在 Vertica 中,非常 要做的第一件事就是查看很好的 SQL 参考手册。在这种情况下,您会发现一个内置函数,用于将表示为 VARBINARY 列的 IPv6 地址转换为字符串。
更简单,更快:
SELECT V6_NTOA(your_column_here) ;