我在二进制文件中有一些数据需要解析。数据被分成 22 个字节的块,所以我正在尝试生成一个元组列表,每个元组包含 22 个值。不过,该文件没有分成几行,所以我在弄清楚如何遍历文件并获取数据时遇到了问题。
如果我这样做,它可以正常工作:
nextList = f.read(22)
newList = struct.unpack("BBBBBBBBBBBBBBBBBBBBBB", nextList)
其中 newList 包含一个包含 22 个值的元组。但是,如果我尝试将类似的逻辑应用于迭代的函数,它就会崩溃。
def getAllData():
listOfAll = []
nextList = f.read(22)
while nextList != "":
listOfAll.append(struct.unpack("BBBBBBBBBBBBBBBBBBBBBB", nextList))
nextList = f.read(22)
return listOfAll
data = getAllData()
给我这个错误:
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
data = getAllData()
File "<pyshell#26>", line 5, in getAllData
listOfAll.append(struct.unpack("BBBBBBBBBBBBBBBBBBBBBB", nextList))
struct.error: unpack requires a bytes object of length 22
我对python相当陌生,所以我不太确定我在这里出了问题。我确信文件中的数据均匀地分解为 22 字节的部分,所以这不是问题。
由于您报告它在len(nextList) == 0
时正在运行,这可能是因为nextList
(不是列表..(是一个空字节对象,不等于空字符串对象:
>>> b"" == ""
False
所以你的生产线中的条件
while nextList != "":
永远不会为真,即使nextList
为空。 这就是为什么使用len(nextList) != 22
作为休息条件起作用的原因,甚至
while nextList:
应该足够了。
read(22)
不能保证返回长度为 22 的字符串。它的合约是从 0 到 22(含(之间的任何位置返回长度字符串。长度为零的字符串表示没有更多要读取的数据。在python 3文件中,文件对象产生bytes
对象而不是str
。 str
和bytes
永远不会被认为是平等的。
如果您的文件很小,那么您最好将整个文件读取到内存中,然后将其拆分为块。
listOfAll = []
data = f.read()
for i in range(0, len(data), 22):
t = struct.unpack("BBBBBBBBBBBBBBBBBBBBBB", data[i:i+22])
listOfAll.append(t)
否则,您将需要做一些更复杂的事情来检查从读取中返回的数据量。
def dataiter(f, chunksize=22, buffersize=4096):
data = b''
while True:
newdata = f.read(buffersize)
if not newdata: # end of file
if not data:
return
else:
yield data
# or raise error as 0 < len(data) < chunksize
# or pad with zeros to chunksize
return
data += newdata
i = 0
while len(data) - i >= chunksize:
yield data[i:i+chunksize]
i += chunksize
try:
data = data[i:] # keep remainder of unused data
except IndexError:
data = b'' # all data was used