Python Convert Binary String to IP Address in Dott

2019-09-09 13:14发布

问题:

So I'm trying to read in a file with some binary strings, i.e: 10000010 00000000 0000**** ********. The script will convert the *'s to both 0 and 1, so there will be two binary strings that look like this:

10000010 00000000 00000000 00000000 and 10000010 00000000 00001111 11111111.

Then the script will convert them to ip addresses, so in this example, my script should return 130.0.0.0 and 130.0.15.255

This is my code so far:

def main():
    text=open('filename', 'r').readlines()
    for line in text:
        words = line.split(" ")
        words_2=list(words)
        for char in words:
            low_range=char.replace('*','0')
            conversion=str(int(low_range, 2))
            decimal='.'.join(map(str,conversion))
            print(decimal)
        for char in words_2:
            high_range=char.replace('*','1')
            conversion_2=str(int(high_range, 2))
            decimal='.'.join(map(str,conversion_2))
            print(decimal)
main()

When I run my code, it prints out:

1.3.0  
0  
0  
0  
1.3.0  
0  
6.3  
2.5.5  
1.3.0  
0  
6.4  
0  
1.3.0  
0  
9.5  
2.5.5  
1.3.0  
0  
1.2.8  
0  
1.3.0  
0  
1.9.1  
2.5.5  
1.3.0  
0  
1.3.0  
0  
1.9.2  
0  
1.3.0  
0  
2.5.5  
2.5.5 

When I really want it to print out:

130.0.0.0  
130.0.63.255  
130.0.64.0  
130.0.95.255  
130.0.128.0  
130.0.191.255  
130.0.192.0  
130.0.255.255  

Can anyone help explain what I am doing wrong?

回答1:

You are joining the letters of byte's decimal representation, while you should join the bytes themselves.

decimal='.'.join(map(str,conversion))

Also you print each byte of an ip on its own line

print(decimal)

Here's how I'd write the loop:

for line in text:
    words = line.split(" ")

    for bit in '01':        
        ip = []
        for word in words:
            byte=word.replace('*', bit)
            ip.append(str(int(byte, 2)))
        print '.'.join(ip)


回答2:

You can use simple formatting:

"%d.%d.%d.%d" % (0b10000010, 0b00000000, 0b00000000, 0b00000000)
# '130.0.0.0'

To read a binary number from a string (say "10000010") use:

int("10000010", 2)
# 130

If you want to work with ip addresses I suggest using ipaddress:

>>> import ipaddress
>>> ipaddress.IPv4Address("%d.%d.%d.%d" % (0b10000010, 0b00000000, 0b00000000, 0b00000000))
IPv4Address('130.0.0.0')

However, it's not available under python 2.x



回答3:

Your example splits the input by whitespace to variable words. Then you iterate over the words, convert them to int and back to string to variable conversion. That all makes sense.

The problem is on following line:

decimal='.'.join(map(str,conversion))

When it get's executed for the first time the value is '130'. The map call is unnecessary, it just turns the conversion to list of strings: ['1', '3', '0']. Then you join the strings together with . so you get 1.3.0 that you seen in the output. Note that you'd get the same result even if you'd remove map since then join would just iterate over characters in the string.

Instead of iterating over the characters just convert every word with int just like you're doing and collect them to a list. Then convert them to strings with either map or list comprehension and finally join them together with ..

Here's a short example that does it:

with open('test.txt') as text:
    for line in text:
        print '.'.join(str(int(x, 2)) for x in line.split())