==============================
5.9 读å–二进制数æ®åˆ°å¯å˜ç¼“冲区ä¸
==============================
----------
问题
----------
ä½ æƒ³ç›´æŽ¥è¯»å–二进制数æ®åˆ°ä¸€ä¸ªå¯å˜ç¼“冲区ä¸ï¼Œè€Œä¸éœ€è¦åšä»»ä½•çš„ä¸é—´å¤åˆ¶æ“作。
æˆ–è€…ä½ æƒ³åŽŸåœ°ä¿®æ”¹æ•°æ®å¹¶å°†å®ƒå†™å›žåˆ°ä¸€ä¸ªæ–‡ä»¶ä¸åŽ»ã€‚
----------
解决方案
----------
ä¸ºäº†è¯»å–æ•°æ®åˆ°ä¸€ä¸ªå¯å˜æ•°ç»„ä¸ï¼Œä½¿ç”¨æ–‡ä»¶å¯¹è±¡çš„ ``readinto()`` 方法。比如:
.. code-block:: python
import os.path
def read_into_buffer(filename):
buf = bytearray(os.path.getsize(filename))
with open(filename, 'rb') as f:
f.readinto(buf)
return buf
䏋颿˜¯ä¸€ä¸ªæ¼”示这个函数使用方法的例å:
.. code-block:: python
>>> # Write a sample file
>>> with open('sample.bin', 'wb') as f:
... f.write(b'Hello World')
...
>>> buf = read_into_buffer('sample.bin')
>>> buf
bytearray(b'Hello World')
>>> buf[0:5] = b'Hello'
>>> buf
bytearray(b'Hello World')
>>> with open('newsample.bin', 'wb') as f:
... f.write(buf)
...
11
>>>
----------
讨论
----------
文件对象的 ``readinto()`` 方法能被用æ¥ä¸ºé¢„先分é…内å˜çš„æ•°ç»„å¡«å……æ•°æ®ï¼Œç”šè‡³åŒ…括由 ``array`` æ¨¡å—æˆ– ``numpy`` 库创建的数组。
和普通 ``read()`` 方法ä¸åŒçš„æ˜¯ï¼Œ ``readinto()`` å¡«å……å·²å˜åœ¨çš„ç¼“å†²åŒºè€Œä¸æ˜¯ä¸ºæ–°å¯¹è±¡é‡æ–°åˆ†é…内å˜å†è¿”回它们。
å› æ¤ï¼Œä½ å¯ä»¥ä½¿ç”¨å®ƒæ¥é¿å…大é‡çš„内å˜åˆ†é…æ“作。
æ¯”å¦‚ï¼Œå¦‚æžœä½ è¯»å–一个由相åŒå¤§å°çš„记录组æˆçš„äºŒè¿›åˆ¶æ–‡ä»¶æ—¶ï¼Œä½ å¯ä»¥åƒä¸‹é¢è¿™æ ·å†™ï¼š
.. code-block:: python
record_size = 32 # Size of each record (adjust value)
buf = bytearray(record_size)
with open('somefile', 'rb') as f:
while True:
n = f.readinto(buf)
if n < record_size:
break
# Use the contents of buf
...
å¦å¤–有一个有趣特性就是 ``memoryview`` ,
它å¯ä»¥é€šè¿‡é›¶å¤åˆ¶çš„æ–¹å¼å¯¹å·²å˜åœ¨çš„缓冲区执行切片æ“作,甚至还能修改它的内容。比如:
.. code-block:: python
>>> buf
bytearray(b'Hello World')
>>> m1 = memoryview(buf)
>>> m2 = m1[-5:]
>>> m2
<memory at 0x100681390>
>>> m2[:] = b'WORLD'
>>> buf
bytearray(b'Hello WORLD')
>>>
使用 ``f.readinto()`` æ—¶éœ€è¦æ³¨æ„çš„æ˜¯ï¼Œä½ å¿…é¡»æ£€æŸ¥å®ƒçš„è¿”å›žå€¼ï¼Œä¹Ÿå°±æ˜¯å®žé™…è¯»å–çš„å—节数。
如果å—节数å°äºŽç¼“冲区大å°ï¼Œè¡¨æ˜Žæ•°æ®è¢«æˆªæ–æˆ–è€…è¢«ç ´å了(æ¯”å¦‚ä½ æœŸæœ›æ¯æ¬¡è¯»å–指定数é‡çš„å—节)。
最åŽï¼Œç•™å¿ƒè§‚察其他函数库和模å—ä¸å’Œ ``into`` 相关的函数(比如 ``recv_into()`` , ``pack_into()`` ç‰)。
Python的很多其他部分已ç»èƒ½æ”¯æŒç›´æŽ¥çš„I/O或数æ®è®¿é—®æ“作,这些æ“作å¯è¢«ç”¨æ¥å¡«å……或修改数组和缓冲区内容。
关于解æžäºŒè¿›åˆ¶ç»“构和 ``memoryviews`` 使用方法的更高级例å,请å‚考6.12å°èŠ‚ã€‚