Print a string in binary format
Bengt Richter
bokr at oz.net
Sat Jan 22 05:11:32 CET 2005
On Sat, 22 Jan 2005 00:45:19 +1000, Nick Coghlan <ncoghlan at iinet.net.au> wrote:
>neutrino wrote:
>> Greetings to the Python gurus,
>>
>> I have a binary file and wish to see the "raw" content of it. So I open
>> it in binary mode, and read one byte at a time to a variable, which
>> will be of the string type. Now the problem is how to print the binary
>> format of that charater to the standard output. It seems a common task
>> but I just cannot find the appropriate method from the documentation.
>> Thanks a lot.
>>
>
>FWIW, I work with serial data a lot, and I find the following list comprehension
>to be a handy output tool for binary data:
>
> print " ".join(["%0.2X" % ord(c) for c in data])
>
>The space between each byte helps keep things from degenerating into a
>meaningless mass of numbers, and using 2-digit hex instead of binary works
>towards the same purpose. (I actually currently use the hex() builtin, but the
>above just occurred to me, and it will give nicer formatting, and avoids the
>C-style "0x" prefixing each byte)
>
>Here's an interesting twiddle, though (there's probably already something along
>these lines in the cookbook):
Looks like you also played with this problem, after Alex posted a request for alternative
one-liner solutions to a question on an Italian newsgroup last October? ("show_base" reminded me
of "number_in_base")
http://groups-beta.google.com/groups?hl=en&lr=&q=number_in_base&qt_s=Search+Groups
BTW, my final version was (which can be put on one line ;-)
def number_in_base(x, N=10, digits='0123456789ABCDEF'):
return '-'[:x<0]+''.join([digits[r] for q in [abs(x)]
for q,r in iter(lambda:divmod(q, N), (0,0))][::-1]) or digits[0]
(it also takes care of sign and lets you encode with alternative digits if you like ;-)
>
>Py> def show_base(val, base, min_length = 1):
>... chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
>... if base < 2: raise ValueError("2 is minimum meaningful base")
>... if base > len(chars): raise ValueError("Not enough characters for base")
>... new_val = []
>... while val:
>... val, remainder = divmod(val, base)
>... new_val.append(chars[remainder])
>... result = "".join(reversed(new_val))
>... return ("0" * (min_length - len(result))) + result
Hm, learn something every day ;-)
It didn't occur to me that a string multiplied by a negative number would default
nicely to the same result as multiplying by zero.
>...
>Py> show_base(10, 2)
>'1010'
>Py> show_base(10, 2, 8)
>'00001010'
>Py> show_base(10, 16, 2)
>'0A'
>Py> show_base(254, 16, 2)
>'FE'
>Py> show_base(0, 16)
>'0'
>Py> for base in range(2, 36):
>... for testval in range(1000):
>... assert testval == int(show_base(testval, base), base)
>...
>Py>
I guess that's a good idea (supplying full set of alphanumeric digits)
>>> def number_in_base(x, N=10, digits='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
... return '-'[:x<0]+''.join([digits[r] for q in [abs(x)]
... for q,r in iter(lambda:divmod(q, N), (0,0))][::-1]) or digits[0]
...
>>> for base in range(2, 36):
... for testval in range(1000):
... assert testval == int(number_in_base(testval, base), base)
...
>>>
For that matter, might as well go for Z base and negatives too:
>>> for base in range(2, 37):
... for testval in range(-500, 500):
... assert testval == int(number_in_base(testval, base), base)
...
>>>
(assert did not complain)
>>> for base in range(2, 37):
... for testval in (-base+2, -base+1, -base, base-2, base-1,base):
... print '%4s:%-4s'%(testval, number_in_base(testval, base)),
... print
...
0:0 -1:-1 -2:-10 0:0 1:1 2:10
-1:-1 -2:-2 -3:-10 1:1 2:2 3:10
-2:-2 -3:-3 -4:-10 2:2 3:3 4:10
-3:-3 -4:-4 -5:-10 3:3 4:4 5:10
-4:-4 -5:-5 -6:-10 4:4 5:5 6:10
-5:-5 -6:-6 -7:-10 5:5 6:6 7:10
-6:-6 -7:-7 -8:-10 6:6 7:7 8:10
-7:-7 -8:-8 -9:-10 7:7 8:8 9:10
-8:-8 -9:-9 -10:-10 8:8 9:9 10:10
-9:-9 -10:-A -11:-10 9:9 10:A 11:10
-10:-A -11:-B -12:-10 10:A 11:B 12:10
-11:-B -12:-C -13:-10 11:B 12:C 13:10
-12:-C -13:-D -14:-10 12:C 13:D 14:10
-13:-D -14:-E -15:-10 13:D 14:E 15:10
-14:-E -15:-F -16:-10 14:E 15:F 16:10
-15:-F -16:-G -17:-10 15:F 16:G 17:10
-16:-G -17:-H -18:-10 16:G 17:H 18:10
-17:-H -18:-I -19:-10 17:H 18:I 19:10
-18:-I -19:-J -20:-10 18:I 19:J 20:10
-19:-J -20:-K -21:-10 19:J 20:K 21:10
-20:-K -21:-L -22:-10 20:K 21:L 22:10
-21:-L -22:-M -23:-10 21:L 22:M 23:10
-22:-M -23:-N -24:-10 22:M 23:N 24:10
-23:-N -24:-O -25:-10 23:N 24:O 25:10
-24:-O -25:-P -26:-10 24:O 25:P 26:10
-25:-P -26:-Q -27:-10 25:P 26:Q 27:10
-26:-Q -27:-R -28:-10 26:Q 27:R 28:10
-27:-R -28:-S -29:-10 27:R 28:S 29:10
-28:-S -29:-T -30:-10 28:S 29:T 30:10
-29:-T -30:-U -31:-10 29:T 30:U 31:10
-30:-U -31:-V -32:-10 30:U 31:V 32:10
-31:-V -32:-W -33:-10 31:V 32:W 33:10
-32:-W -33:-X -34:-10 32:W 33:X 34:10
-33:-X -34:-Y -35:-10 33:X 34:Y 35:10
-34:-Y -35:-Z -36:-10 34:Y 35:Z 36:10
>>>
Of course, this is the prefixed-sign and absolute value representation,
which is no good if you are using base 2, 8, or 16 to get an idea of
underlying bits in a negative two-s complement representation.
But that's another thread ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list