5.4 读写å—节数æ�®Â¶
问题¶
ä½ æƒ³è¯»å†™äºŒè¿›åˆ¶æ–‡ä»¶ï¼Œæ¯”å¦‚å›¾ç‰‡ï¼Œå£°éŸ³æ–‡ä»¶ç‰ç‰ã€‚
解决方案¶
使用模�为 rb 或 wb 的 open() 函数�读�或写入二进制数�。比如:
# Read the entire file as a single byte string
with open('somefile.bin', 'rb') as f:
data = f.read()
# Write binary data to a file
with open('somefile.bin', 'wb') as f:
f.write(b'Hello World')
在读å�–二进制数æ�®æ—¶ï¼Œéœ€è¦�指明的是所有返回的数æ�®éƒ½æ˜¯å—节å—ç¬¦ä¸²æ ¼å¼�的,而ä¸�是文本å—符串。 类似的,在写入的时候,必须ä¿�è¯�å�‚数是以å—节形å¼�对外暴露数æ�®çš„对象(比如å—节å—符串,å—节数组对象ç‰)。
讨论¶
在读å�–二进制数æ�®çš„æ—¶å€™ï¼Œå—节å—符串和文本å—符串的è¯ä¹‰å·®å¼‚å�¯èƒ½ä¼šå¯¼è‡´ä¸€ä¸ªæ½œåœ¨çš„陷阱。 特别需è¦�注æ„�的是,索引和è¿ä»£åŠ¨ä½œè¿”å›žçš„æ˜¯å—节的值而ä¸�是å—节å—符串。比如:
>>> # Text string
>>> t = 'Hello World'
>>> t[0]
'H'
>>> for c in t:
... print(c)
...
H
e
l
l
o
...
>>> # Byte string
>>> b = b'Hello World'
>>> b[0]
72
>>> for c in b:
... print(c)
...
72
101
108
108
111
...
>>>
å¦‚æžœä½ æƒ³ä»ŽäºŒè¿›åˆ¶æ¨¡å¼�的文件ä¸è¯»å�–或写入文本数æ�®ï¼Œå¿…须确ä¿�è¦�进行解ç �和编ç �æ“�作。比如:
with open('somefile.bin', 'rb') as f:
data = f.read(16)
text = data.decode('utf-8')
with open('somefile.bin', 'wb') as f:
text = 'Hello World'
f.write(text.encode('utf-8'))
二进制I/O还有一个鲜为人知的特性就是数组和C结构体类型能直接被写入,而ä¸�需è¦�ä¸é—´è½¬æ�¢ä¸ºè‡ªå·±å¯¹è±¡ã€‚比如:
import array
nums = array.array('i', [1, 2, 3, 4])
with open('data.bin','wb') as f:
f.write(nums)
这个适用于任何实现了被称之为â€�缓冲接å�£â€�的对象,这ç§�对象会直接暴露其底层的内å˜ç¼“冲区给能处ç�†å®ƒçš„æ“�作。 二进制数æ�®çš„写入就是这类æ“�作之一。
很多对象还å…�许通过使用文件对象的 readinto() 方法直接读å�–二进制数æ�®åˆ°å…¶åº•层的内å˜ä¸åŽ»ã€‚æ¯”å¦‚ï¼š
>>> import array
>>> a = array.array('i', [0, 0, 0, 0, 0, 0, 0, 0])
>>> with open('data.bin', 'rb') as f:
... f.readinto(a)
...
16
>>> a
array('i', [1, 2, 3, 4, 0, 0, 0, 0])
>>>
但是使用这ç§�技术的时候需è¦�æ ¼å¤–å°�å¿ƒï¼Œå› ä¸ºå®ƒé€šå¸¸å…·æœ‰å¹³å�°ç›¸å…³æ€§ï¼Œå¹¶ä¸”å�¯èƒ½ä¼šä¾�èµ–å—é•¿å’Œå—节顺åº�(高ä½�优先和低ä½�优先)。 å�¯ä»¥æŸ¥çœ‹5.9å°�节ä¸å�¦å¤–一个读å�–二进制数æ�®åˆ°å�¯ä¿®æ”¹ç¼“冲区的例å�。