我是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”,我能逐行阅读吗?我不确定它是否是每行一个值...我基本上经过并逐字逐句地计算出哪些标头值位于哪里。
任何帮助都将不胜感激!!
答案 0 :(得分:2)
您将文件的全部内容读入didson_data
,然后将文件处理程序didson_file
恢复为零,并且从未将所有字段从{{1并且没有单步执行文件中的行/块,所以当然你的第二个didson_data
仍然位于零位置,因为你没有移动到任何地方,因为你寻求定位零。
答案 1 :(得分:0)
为什么不继续一次性读取所有标题,而不是整个文件。然后,您的文件将准备好开始读取标题之后的数据。看起来更改了read
:
didson_data=didson_file.read()
pos=didson_file.seek(0,0)
只是:
didson_data=didson_file.read(377)
只会这样做,将位置保留在十进制偏移量377处,紧接在frameinterval标题之后。
没有理由让保存这么少的内存变得更加复杂。
一种更通用的解决方案,用于读取变量块中的其余文件,并跟踪您的位置,将使用您自己的函数。它可以读取文件的大小足以容纳最大可能的数据元素,找出数据元素的实际大小,将数据元素保存为字符串,寻找(函数开始时文件中的传入偏移量)+(刚检索的数据元素的长度,然后返回数据元素字符串。
基本上:
您将被要求越过标题然后重复调用
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
直到它返回Null
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函数的想法很好 - 但是你必须调整你从中学到的东西,而不是从中复制。我假设它是一个生成器函数,这是一个很酷的主意,并且可以记住从函数调用到下一个函数的各种状态。但是因为你只需要记住你在文件中的位置,这种事情可以起作用并且更容易理解(但是时间效率要低一点)。
答案 2 :(得分:0)
如果您的文件是二进制数据,并且它只是几兆字节,您可能希望立即阅读整个文件。这就是您现在正在使用didson_file.read()
。
如果文件是文本数据,按行组织,有一个很好的习惯用法可以方便地一次处理一行:
with open("my_file_name") as f:
for line in f:
do_something_with_line(line)
实际上,由于你需要解析那些结构,很明显你正在读取二进制文件。在这种情况下,你应该啜饮整个事情(如果内存使用不是问题),或者以块的形式读取它(更复杂,但会降低内存使用率)。