neutrino said:
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)
... 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 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 testval in range(-500, 500):
... assert testval == int(number_in_base(testval, base), base)
...(assert did not complain)
... 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
14:10
-13:-D -14:-E -15:-10 13
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
-26:-10 24:O 25
26:10
-25
-26:-Q -27:-10 25
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