prev | Version 1107 (Mon Nov 27 20:46:05 2006) | next |
"10239472"
is 8 bytes long, but the 32-bit integer it represents is 4 bytes"34"
to the one represented by "57"
Figure 18.1: Two's Complement
Name | Symbol | Purpose | Example |
---|---|---|---|
And | & | 1 if both bits are 1, 0 otherwise | 0110 & 1010 = 0010 |
Or | | | 1 if either bit is 1 | 0110 & 1010 = 1110 |
Xor | ^ | 1 if the bits are different, 0 if they're the same | 0110 & 1010 = 1100 |
Not | ~ | Flip each bit | ~0110 = 1001 |
Table 18.1: Bitwise Operators in Python |
def format_bits(val, width=1): '''Create a base-2 representation of an integer.''' result = '' while val: if val & 0x01: result = '1' + result else: result = '0' + result val = val >> 1 if len(result) < width: result = '0' * (width - len(result)) + result return result tests = [ [ 0, None, '0'], [ 0, 4, '0000'], [ 5, None, '101'], [19, 8, '00010011'] ] for (num, width, expected) in tests: if width is None: actual = format_bits(num) else: actual = format_bits(num, width) print '%4d %8s %10s %10s' % (num, width, expected, actual)
0 None 0 0 0 4 0000 0000 5 None 101 101 19 8 00010011 00010011
x << N
and
, or
, and not
to set specific bits to 1 or 0x
to 1:mask
in which bit i is 1 and all others are 0x = x | mask
x
to 0:mask
in which bit i is 1 and all others are 0~
, so that the ith bit is 0, and all the others are 1x = x & mask
Figure 18.2: Setting and Clearing Bits
Figure 18.3: Using Bits to Record Sets of Flags
# hex binary MERCURY = 0x01 # 0001 PHOSPHORUS = 0x02 # 0010 CHLORINE = 0x04 # 0100 # Sample contains mercury and chlorine sample = MERCURY | CHLORINE print 'sample: %04x' % sample # Check for various elements for (flag, name) in [[MERCURY, "mercury"], [PHOSPHORUS, "phosphorus"], [CHLORINE, "chlorine"]]: if sample & flag: print 'sample contains', name else: print 'sample does not contain', name
sample: 0005 sample contains mercury sample does not contain phosphorus sample contains chlorine
Figure 18.5: Uneven Spacing of Floating-Point Numbers
f.read(N)
reads (up to) next N bytesf
is empty, returns None
f.write(str)
writes the bytes in the string str
input = open(filename, 'rb')
(and similarly for output)"\r\n"
to Unix-style "\n"
…"r"
, then in "rb"
import sys print sys.platform for mode in ('r', 'rb'): f = open('open_binary.py', mode) s = f.read(40) f.close() print repr(s)
cygwin 'import sys\r\nprint sys.platform\r\nfor mode'
linux 'import sys\nprint sys.platform\nfor mode in '
fwrite(&array, sizeof(int), 3, file)
will write 3 4-byte integers to a fileFigure 18.6: C Storage vs. Python Storage
Figure 18.7: Packing Data
struct
module to pack and unpackpack(fmt, v1, v2, …)
packs the values v1
, v2
, etc. according to fmt
, returning a stringunpack(fmt, str)
unpacks the values in str
according to fmt
, returning a tupleimport struct fmt = 'hh' # two 16-bit integers x = 31 y = 65 binary = struct.pack(fmt, x, y) print 'binary representation:', repr(binary) normal = struct.unpack(fmt, binary) print 'back to normal:', normal
binary representation: '\x1f\x00A\x00' back to normal: (31, 65)
'\x1f\x00A\x00'
?['\x1f', '\x00', 'A', '\x00']
"A"
is 6510Format | Meaning |
---|---|
"c" | Single character (i.e., string of length 1) |
"B" | Unsigned 8-bit integer |
"h" | Short (16-bit) integer |
"i" | 32-bit integer |
"f" | 32-bit float |
"d" | Double-precision (64-bit) float |
"2" | String of fixed size (see below) |
Table 18.2: Packing Format Specifiers |
"4i"
is four integers"B"
or "h"
instead of the full 32"4s"
for a 4-character stringunpack
know how much data to use?calcsize(fmt)
calculates how large (in bytes) the data produced using fmt
will beimport struct packed = struct.pack('4c', 'a', 'b', 'c', 'd') print 'packed string:', repr(packed) left16, right16 = struct.unpack('hh', packed) print 'as two 16-bit integers:', left16, right16 all32 = struct.unpack('i', packed) print 'as a single 32-bit integer', all32[0] float32 = struct.unpack('f', packed) print 'as a 32-bit float', float32[0]
packed string: 'abcd' as two 16-bit integers: 25185 25699 as a single 32-bit integer 1684234849 as a 32-bit float 1.67779994081e+22
Figure 18.8: Packing a Variable-Length Vector
def pack_vec(vec): buf = struct.pack('i', len(vec)) for v in vec: buf += struct.pack('i', v) return buf def unpack_vec(buf): # Get the count of the number of elements in the vector. int_size = struct.calcsize('i') count = struct.unpack('i', buf[0:int_size])[0] # Get 'count' values, one by one. pos = int_size result = [] for i in range(count): v = struct.unpack('i', buf[pos:pos+int_size]) result.append(v[0]) pos += int_size return result
def unpack_vec(buf): # Get the count of the number of elements in the vector. int_size = struct.calcsize('i') count = struct.unpack('i', buf[0:int_size])[0] # Get 'count' values, one by one. pos = int_size result = [] for i in range(count): v = struct.unpack('i', buf[pos:pos+int_size]) result.append(v[0]) pos += int_size return result
def pack_strings(strings): result = '' for s in strings: length = len(s) format = 'i%ds' % length result += struct.pack(format, length, s) return result def unpack_strings(buf): int_size = struct.calcsize('i') pos = 0 result = [] while pos < len(buf): length = struct.unpack('i', buf[pos:pos+int_size])[0] pos += int_size format = '%ds' % length s = struct.unpack(format, buf[pos:pos+length])[0] pos += length result.append(s) return result
def unpack_strings(buf): int_size = struct.calcsize('i') pos = 0 result = [] while pos < len(buf): length = struct.unpack('i', buf[pos:pos+int_size])[0] pos += int_size format = '%ds' % length s = struct.unpack(format, buf[pos:pos+length])[0] pos += length result.append(s) return result
Figure 18.9: Structure of a Binary File With Metadata
def store(outf, format, values): '''Store a list of lists, each of which has the same structure.''' length = struct.pack('i', len(format)) outf.write(length) outf.write(format) for v in values: temp = [format] + v binary = struct.pack(*temp) outf.write(binary)
struct.pack
is calledstruct.pack
to itstore
def retrieve(inf): '''Retrieve data from a self-describing file.''' data = inf.read(struct.calcsize('i')) format_length = struct.unpack('i', data)[0] format = inf.read(format_length) record_size = struct.calcsize(format) result = [] while True: data = inf.read(record_size) if not data: break values = list(struct.unpack(format, data)) result.append(values) return result
from cStringIO import StringIO tests = [ ['i', [[17]]], ['ii', [[17, 18]]], ['ii', [[17, 18], [19, 20], [21, 22]]], ['if', [[17, 18.0], [19, 20.0]]] ] for (format, original) in tests: storage = StringIO() temp = store(storage, format, original) storage.seek(0) final = retrieve(storage) assert original == final
prev | Copyright © 2005-06 Python Software Foundation. | next |