我是Python的超级初学者;我宁愿被扔进深渊。 一些背景:我们正在读取的文件来自声纳成像相机;目前,我正在尝试读取写入文件的属性,例如日期,文件名,帧数,光束数等。 首先,我想阅读 FILE 标头。 然后,对于每一帧,我想在 FRAME 标题中读取。我需要在文件头中断的帧标题中读取......我相信我需要 seek() 才能做到这一点。 这是我目前拥有的代码,用于读取文件头(成功完成)并从帧头的信息结束处开始:
编辑的代码:
import math, struct
def __init__(didson):
print "this better work"
def get_file_header(data,offset=0):
fileheader={}
winlengths=[1.125,2.25,4.5,9,18,36]
fileheader['filetype']=struct.unpack("3s",didson_data[0:3])
fileheader['fileversion']=struct.unpack('B',didson_data[3:4])[0]
fileheader['numframes']=struct.unpack('l',didson_data[4:8])
fileheader['framerate']=struct.unpack('l',didson_data[8:12])
fileheader['resolution']=struct.unpack('i',didson_data[12:16])
fileheader['numbeams']=struct.unpack('i',didson_data[16:20])
fileheader['samplerate']=struct.unpack('f',didson_data[20:24])
fileheader['samplesperchannel']=struct.unpack('l',didson_data[24:28])
fileheader['receivergain']=struct.unpack('l',didson_data[28:32])
fileheader['windowstart']=struct.unpack('i',didson_data[32:36])
fileheader['winlengthsindex']=struct.unpack('i',didson_data[36:40])
fileheader['reverse']=struct.unpack('l',didson_data[40:44])
fileheader['serialnumber']=struct.unpack('l',didson_data[44:48])
fileheader['date']=struct.unpack("10s",didson_data[48:58])
#fileheader['???']=struct.unpack('26s',didson_data[58:84])
fileheader['idstring']=struct.unpack("33s",didson_data[84:117])
#fileheader['????2']=struct.unpack('235s',didson_data[117:352])
fileheader['framestart']=struct.unpack('i',didson_data[352:356])
fileheader['frameend']=struct.unpack('i',didson_data[356:360])
fileheader['timelapse']=struct.unpack('i',didson_data[360:364])
fileheader['recordInterval']=struct.unpack('i',didson_data[364:368])
fileheader['radioseconds']=struct.unpack('i',didson_data[368:372])
fileheader['frameinterval']=struct.unpack('i',didson_data[372:376])
return fileheader
def num_datagrams(didson_data):
assert(len(didson_data) % datagram_size==0)
return len(didson_data)/datagram_size
def get_offset(datagram_number):
return datagram_number * datagram_size
def didson_print(fileheader):
print fileheader
for key in fileheader:
print ' ',key, fileheader[key]
def main():
didson_file=open('C:/vprice/DIDSON/DIDSON Data/test.ddf', 'rb')
didson_data=didson_file.read()
print 'Number of datagrams:', num_datagrams(didson_data)
didson_print(datagram)
if __name__=='main':
main()
现在,如果我运行"main",我可以逐行读取吗? 我不确定它是否是每行一个值...我基本上逐个字节地检查并找出哪些标头值位于何处。
任何帮助将不胜感激!!
您将文件的全部内容读入didson_data
,然后查找文件处理程序didson_file
归零,并且永远不要再次使用它,因为您将所有字段从didson_data
中拆分出来,而不是逐步执行文件中的行/块,因此当然您的第二个.tell()
仍将位于位置零,因为自从您寻求位置零以来您没有移动到任何地方。
如果你的文件是二进制数据,并且如果它只有几兆字节,你可能希望一次阅读整个内容。 这就是您现在正在对didson_file.read()
做的事情.
如果文件是文本数据,组织成行,则有一个很好的成语,您可以使用它方便地一次处理一行:
with open("my_file_name") as f:
for line in f:
do_something_with_line(line)
实际上,由于您有需要解析的结构,因此很明显您正在读取二进制文件。 在这种情况下,你应该要么啜饮整个事情(如果内存使用不是问题),要么分块读取它(更复杂,但保持内存使用量)。
为什么不继续一次性读取所有标头,而不是整个文件。然后,您的文件将被定位,准备好开始读取标头后的数据。看起来read
从:
didson_data=didson_file.read()
pos=didson_file.seek(0,0)
只是:
didson_data=didson_file.read(377)
只会这样做,将位置保留在十进制偏移量 377,紧跟在帧间隔标头之后。
没有理由使这更复杂以节省如此少的内存。
以可变块的形式读取文件的其余部分并跟踪您所在位置的更通用的解决方案是使用您自己的函数。它可以读取大小足以容纳最大数据元素的文件,计算出数据元素的实际大小,将数据元素保存到字符串中,查找(函数开始时文件中的传入偏移量)+(刚刚检索的数据元素的长度),然后返回数据元素字符串。
基本上:
您将被要求通过标题,然后反复调用
def get_chunk(fileobject):
result = fileobject.read(1024)
if len(result) == 0: # End of file
return Null
## Determine what this is = thing
fileobject.seek(fileobject.tell()-1024+len(thing)
return thing
直到它返回一个空
值 while True:
the_thing = get_chunk(didson_file)
if not the_thing: # It's a Null--it's the end of the file
return
# process the_thing
# End the program
一旦你通过了标题,你将不得不有一种以某种方式解析对象的方法,并确定它有多长。get_chunk函数可以在 Python 中返回不同类型的对象。仅通过查看the_think类型,*#process the_thing*部分就可以对不同类型的数据执行不同的操作。
对于真正的二进制文件,不应使用readlines函数。数据中的任何换行都是偶然的,因此您不希望使用它们来分解文件。然而,查看readlines函数的想法是一个很好的想法 - 但你必须调整你从中学到的东西,而不是从中复制。我假设它是一个生成器函数,这是一个很酷的想法,并且可以记住从函数的一个调用到下一个调用的各种状态。但是由于您只需要记住您在文件中的位置,因此这种事情可以工作并且更容易理解(但时间效率较低)。