3

我是 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”,我可以逐行阅读吗?我不确定它是否是每行一个值...我基本上逐个字节地计算出哪些标头值位于何处。

任何帮助,将不胜感激!!

4

3 回答 3

2

您将文件的全部内容读入didson_data,然后将文件处理程序didson_file恢复为零,并且不再使用它,因为您将所有字段从文件中拆分出来,didson_data而不是单步执行文件中的行/块,所以当然是您的第二个.tell()仍将位于零位,因为自从您寻求零位以来,您没有移动任何地方。

于 2012-05-23T19:20:14.540 回答
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 函数的想法是一个很好的想法——但你必须调整你从中学到的东西,而不是从中复制。我假设它是一个生成器函数,这是一个很酷的想法,并且可以记住从函数的一次调用到下一次调用的各种状态。但是由于您只需要记住您在文件中的位置,因此这种事情可以工作并且更易于理解(但时间效率稍低)。

于 2012-05-23T20:01:50.647 回答
0

如果您的文件是二进制数据,并且只有几兆字节,您可能希望一次读取整个文件。这就是你现在正在做的事情didson_file.read()

如果文件是文本数据,按行组织,有一个很好的习惯用法,您可以使用它方便地一次处理一行:

with open("my_file_name") as f:
    for line in f:
        do_something_with_line(line)

实际上,由于您拥有需要解析的那些结构,因此很明显您正在读取二进制文件。在这种情况下,您应该吞下整个东西(如果内存使用不是问题),或者分块读取它(更复杂,但会降低内存使用)。

于 2012-05-23T20:34:32.187 回答